Rex
view release on metacpan or search on metacpan
lib/Rex/Commands/Fs.pm view on Meta::CPAN
#
# (c) Jan Gehring <jan.gehring@gmail.com>
#
=head1 NAME
Rex::Commands::Fs - File system commands
=head1 DESCRIPTION
With this module you can do file system tasks like creating directories, deleting or moving files, and more.
=head1 SYNOPSIS
my @files = list_files "/etc";
unlink("/tmp/file");
rmdir("/tmp");
mkdir("/tmp");
my %stat = stat("/etc/passwd");
my $link = readlink("/path/to/a/link");
symlink("/source", "/dest");
rename("oldname", "newname");
chdir("/tmp");
is_file("/etc/passwd");
is_dir("/etc");
is_writeable("/tmp");
is_writable("/tmp");
chmod 755, "/tmp";
chown "user", "/tmp";
chgrp "group", "/tmp";
=head1 EXPORTED FUNCTIONS
=cut
package Rex::Commands::Fs;
use v5.14.4;
use warnings;
our $VERSION = '1.16.1'; # VERSION
require Rex::Exporter;
use Data::Dumper;
use Fcntl;
use Rex::Helper::File::Spec;
use Rex::Helper::SSH2;
use Rex::Helper::Path;
use Rex::Commands;
use Rex::Interface::Fs;
use Rex::Interface::Exec;
use Rex::Interface::File;
use File::Basename;
use Rex::Commands::MD5;
use vars qw(@EXPORT);
use base qw(Rex::Exporter);
@EXPORT = qw(list_files ls
unlink rm rmdir mkdir stat readlink symlink ln rename mv chdir cd cp
chown chgrp chmod
is_file is_dir is_readable is_writeable is_writable is_symlink
df du
mount umount
glob);
use vars qw(%file_handles);
=head2 Changing content
These commands are supposed to change the contents of the file system.
=head3 symlink($from, $to)
This function will create a symbolic link from C<$from> to C<$to>.
task "symlink", "server01", sub {
symlink("/var/www/versions/1.0.0", "/var/www/html");
};
=cut
sub symlink {
my ( $from, $to ) = @_;
$from = resolv_path($from);
$to = resolv_path($to);
Rex::get_current_connection()->{reporter}
->report_resource_start( type => "symlink", name => $to );
my $fs = Rex::Interface::Fs->create;
if ( $fs->is_symlink($to) && $fs->readlink($to) eq $from ) {
Rex::get_current_connection()->{reporter}->report( changed => 0, );
}
else {
$fs->ln( $from, $to ) or die("Can't link $from -> $to");
Rex::get_current_connection()->{reporter}
->report( changed => 1, message => "Symlink created: $from -> $to." );
}
Rex::get_current_connection()->{reporter}
->report_resource_end( type => "symlink", name => $to );
return 1;
}
=head3 ln($from, $to)
C<ln> is an alias for C<symlink>
=cut
sub ln {
&symlink(@_);
}
=head3 unlink($file)
This function will remove the given C<$file>.
task "unlink", "server01", sub {
lib/Rex/Commands/Fs.pm view on Meta::CPAN
=back
With Rex-0.45 and newer, please use the L<file|Rex::Commands::File#file> resource instead.
task "prepare", sub {
file "/tmp",
ensure => "directory",
owner => "root",
group => "root",
mode => 1777;
};
Direct usage:
task "mkdir", "server01", sub {
mkdir "/tmp";
mkdir "/tmp",
owner => "root",
group => "root",
mode => 1777;
};
=cut
sub mkdir {
Rex::Logger::debug("Creating directory $_[0]");
my $dir = shift;
$dir = resolv_path($dir);
my $options = {@_};
$options->{on_change} //= sub { };
Rex::get_current_connection()->{reporter}
->report_resource_start( type => "mkdir", name => $dir );
my $fs = Rex::Interface::Fs->create;
my $not_created = 0;
my %old_stat;
my $changed = 0;
if ( $fs->is_dir($dir) ) {
$not_created = 1;
%old_stat = &stat($dir);
}
my $mode = $options->{"mode"} || 755;
my $owner = $options->{"owner"} || "";
my $group = $options->{"group"} || "";
my $not_recursive = $options->{"not_recursive"} || 0;
if ($not_recursive) {
if ( !$fs->mkdir($dir) ) {
Rex::Logger::debug("Can't create directory $dir");
die("Can't create directory $dir");
}
&chown( $owner, $dir ) if $owner;
&chgrp( $group, $dir ) if $group;
&chmod( $mode, $dir ) if $mode;
}
else {
if ( !Rex::Helper::File::Spec->file_name_is_absolute($dir) ) {
$dir = Rex::Helper::File::Spec->rel2abs($dir);
}
my @directories = __splitdir($dir);
my $path_so_far = shift @directories;
for my $part (@directories) {
$path_so_far = Rex::Helper::File::Spec->join( $path_so_far, $part );
if ( !is_dir($path_so_far) && !is_file($path_so_far) ) {
if ( !$fs->mkdir($path_so_far) ) {
Rex::Logger::debug("Can't create directory $dir");
die("Can't create directory $dir");
}
&chown( $owner, $path_so_far ) if $owner;
&chgrp( $group, $path_so_far ) if $group;
&chmod( $mode, $path_so_far ) if $mode;
}
}
}
my %new_stat = &stat($dir);
if ( !$not_created ) {
Rex::get_current_connection()->{reporter}
->report( changed => 1, message => "Directory created." );
$changed = 1;
}
if ( %old_stat && $old_stat{uid} != $new_stat{uid} ) {
Rex::get_current_connection()->{reporter}
->report( changed => 1, message => "Owner updated." );
$changed = 1;
}
if ( %old_stat && $old_stat{gid} != $new_stat{gid} ) {
Rex::get_current_connection()->{reporter}
->report( changed => 1, message => "Group updated." );
$changed = 1;
}
if ( %old_stat && $old_stat{mode} ne $new_stat{mode} ) {
Rex::get_current_connection()->{reporter}
->report( changed => 1, message => "Mode updated." );
$changed = 1;
}
if ( $changed == 0 ) {
Rex::get_current_connection()->{reporter}->report( changed => 0, );
}
else {
$options->{on_change}->($dir);
}
Rex::get_current_connection()->{reporter}
->report_resource_end( type => "mkdir", name => $dir );
return 1;
}
sub __splitdir {
return Rex::Helper::File::Spec->splitdir(shift);
}
=head3 chown($owner, $path)
Change the owner of a file or a directory.
chown "www-data", "/var/www/html";
chown "www-data", "/var/www/html",
recursive => 1;
This command will not be reported.
If you want to use reports, please use the L<file|Rex::Commands::File#file> resource instead.
=cut
sub chown {
my ( $user, $file, @opts ) = @_;
$file = resolv_path($file);
my $fs = Rex::Interface::Fs->create;
$fs->chown( $user, $file, @opts ) or die("Can't chown $file");
}
=head3 chgrp($group, $path)
Change the group of a file or a directory.
chgrp "nogroup", "/var/www/html";
chgrp "nogroup", "/var/www/html",
recursive => 1;
This command will not be reported.
If you want to use reports, please use the L<file|Rex::Commands::File#file> resource instead.
=cut
sub chgrp {
my ( $group, $file, @opts ) = @_;
$file = resolv_path($file);
my $fs = Rex::Interface::Fs->create;
$fs->chgrp( $group, $file, @opts ) or die("Can't chgrp $file");
}
=head3 chmod($mode, $path)
Change the permissions of a file or a directory.
chmod 755, "/var/www/html";
chmod 755, "/var/www/html",
recursive => 1;
This command will not be reported.
If you want to use reports, please use the L<file|Rex::Commands::File#file> resource instead.
=cut
sub chmod {
my ( $mode, $file, @opts ) = @_;
$file = resolv_path($file);
my $fs = Rex::Interface::Fs->create;
$fs->chmod( $mode, $file, @opts ) or die("Can't chmod $file");
}
=head3 rename($old, $new)
This function will rename C<$old> to C<$new>. Will return 1 on success and 0 on failure.
task "rename", "server01", sub {
rename("/tmp/old", "/tmp/new");
};
=cut
( run in 0.308 second using v1.01-cache-2.11-cpan-5511b514fd6 )