Какво е това връщане на системна команда?

Имам такъв модул. Първо искам да обясня всички logger($arg1,$arg2) извежда изход на конзолата, тя просто е създадена за това. А параметрите $source_server,@source_user,@log_name_pattern,@log_name_pattern,@archive_interval,@move_interval се четат от .csv файл, няма проблем с тях.

use constant OUTPUT_PATH => "./outputs/";
use constant MAX_COMMAND_LENGTH => 100000;
my $cmd_bash = "bash";
my $cmd_source = "source .profile";
sub run_remote_command_with_login
{
    my $start_time = time;
    my $host = shift;
    my $cmd = shift;
    my $user = shift;
    my $pwd = shift;
    my $is_import = 1 if (shift);

    if(length($cmd) > MAX_COMMAND_LENGTH)
    {
        logger(ERROR, "The command will not be run as it is longer than ".MAX_COMMAND_LENGTH." characters");
        return 0;
    }


    logger(DEBUG, "Opening telnet for ".$host." with user $user");

    $t = new Net::Telnet (Timeout => TIMEOUT, Errmode => ERRORMODE, Prompt => '/([>\$%~]|Logging out)\s*$/');
    $t->open($host);

    unless($t->login($user, $pwd)){
        logger(WARNING, "Login failed with return value $response");
        logger(WARNING, "Login failed to $host with user $user");
        return "";
    }
    $t->max_buffer_length(BUFFER);

    my @lines = $t->cmd($cmd_bash);
    @lines = $t->cmd($cmd_source);

    logger(DEBUG, "Running command: ".$cmd);

    if ($is_import)
    {
        $t->print($cmd);
        ($prematch, $match) = $t->waitfor('/.*Logging out.*/i');
        @lines = split(/\n/, $prematch);
        $ok = $t->close;
    }
    else
    {
        @lines = $t->cmd($cmd);
        $ok = $t->close;
    }   

    if($ok)
    {
        logger(DEBUG, "Closed telnet for ".$host);
    }
    else
    {
        logger(WARNING, "Could not close telnet for ".$host);
        logger(WARNING, "Error code: ".$ok);
    }

    logger(DEBUG, "Output lines are:"); 
    for($i = 0; $i < scalar(@lines); $i++)
    {
        logger(DEBUG, $lines[$i]);
    }
    logger(DEBUG, "End of output lines.");

    if (not -d OUTPUT_PATH)
    {
        my $cmd = "mkdir ".OUTPUT_PATH;
        `$cmd`;
    }
    my $out = OUTPUT_PATH.$start_time.".txt";
    open(DAT2, ">$out") || die("Could not open file!");
    logger(INFO, "Remote command execution finished in ".(time - $start_time)." seconds. (Output: $out)");

    for (my $i = 0; $i < scalar(@lines); $i++)
    {
        print DAT2 $lines[$i]."\n";
    }
    close(DAT2);

    return \@lines;
}

Този модул е ​​написан за Telnet връзка с отдалечен сървър и работи добре. Но ние имаме някои Linux сървъри и те искаха да свържа тези сървъри чрез SSH. Не е проблем, но в този отдалечен хост искахме да архивираме или преместваме файлове. Имаме модули като този в Archive.pl:

sub archive
{
    my $cmd_list = "find $source_dir -name \"$log_name_pattern\" -a ! -name \"*.gz\" -a ! -mtime -$archive_interval -a ! -size 0 -a -type f";
    my $cmd_gzip = "find $source_dir -name \"$log_name_pattern\" -a ! -name \"*.gz\" -a ! -mtime -$archive_interval -a ! -size 0 -a -type f -exec gzip {} \\;";

    Utilities::logger(Utilities::INFO,"Running command: $cmd_list");

    my $output = Utilities::run_remote_command_with_login($source_server, $cmd_list, $source_user, get_pwd($source_user));

    extract_files(\@$output);

    if(scalar(@$output) == 0)
    {
        Utilities::logger(Utilities::INFO,"No files found to archive.");
    }
    else
    {
        Utilities::logger(Utilities::INFO, scalar(@$output)." file(s) will be zipped:");
        for(my $i = 0; $i < scalar(@$output); $i++)
        {
            print $$output[$i];
        }   

        Utilities::logger(Utilities::INFO,"Running command: $cmd_gzip");
        if($source_user == "picshot"){
            $output = Utilities::run_remote_command_with_login($source_server, $cmd_gzip, $source_user, get_pwd($source_user));
        }
        else{
            $output = Utilities::run_remote_command_with_login($source_server, $cmd_gzip, $source_user, get_pwd($source_user));
        }
    }
}

sub move
{   
    my $cmd_filelist = "find $source_dir -name \"$log_name_pattern.gz\" -a ! -mtime -$move_interval -a -type f";
    Utilities::logger(Utilities::INFO,"Running command: $cmd_filelist");
    my $output = Utilities::run_remote_command_with_login($source_server, $cmd_filelist, $source_user, get_pwd($source_user));

    extract_files(\@$output);

    if(scalar(@$output) == 0)
    {
        Utilities::logger(Utilities::INFO,"No files found to move");
    }
    else
    {
        Utilities::logger(Utilities::INFO, scalar(@$output)." file(s) will be moved:");
        for(my $i = 0; $i < scalar(@$output); $i++)
        {
            print $$output[$i];
        }   

        if($source_server ne $target_server)
        {
            my $to_delete = Utilities::run_remote_ftp($source_server, $source_dir, $source_user, $source_user, $target_server, $target_dir, $target_user, $target_user, $output);

            if(scalar(@$to_delete) == 0)
            {
                Utilities::logger(Utilities::WARNING,"FTP put returned no files, keeping source files");
            }
            else
            {
                Utilities::logger(Utilities::INFO,"FTP put finished. Removing files returned by PUT");
                my $cmd_delete = "rm ";

                for(my $i = 0; $i < scalar(@$to_delete); $i++)
                {
                    $$to_delete[$i] = Utilities::trim($$to_delete[$i]);
                    $cmd_delete = $cmd_delete.$$to_delete[$i]." ";
                }
                Utilities::logger(Utilities::INFO,"Running command: $cmd_delete");
                Utilities::run_remote_command_with_login($source_server, $cmd_delete, $source_user, get_pwd($source_user));
            }
        }
        else
        {
            my $cmd_move = "mv ";
            for(my $i = 0; $i < scalar(@$output); $i++)
            {
                $$output[$i] = Utilities::trim($$output[$i]);
                $cmd_move = $cmd_move." ".$$output[$i];
            }
            $cmd_move = $cmd_move." ".$target_dir;

            # Create target dir if it does not exist.
            my $cmd_create_dir = "mkdir -p ".$target_dir;
            Utilities::logger(Utilities::INFO,"Running command: $cmd_create_dir");
            my $output = Utilities::run_remote_command_with_login($target_server, $cmd_create_dir, $target_user, get_pwd($target_user));

            Utilities::logger(Utilities::INFO,"Running command to move files");
            Utilities::logger(Utilities::INFO,"Running command: $cmd_move");
            $output = Utilities::run_remote_command_with_login($target_server, $cmd_move, $target_user, get_pwd($target_user));
            Utilities::check_move_cmd($output);
        }
    }
}

Тези два модула работят добре. Те успешно архивират и преместват файлове.

Направих ssh-keygen it RSA конфигурация между сървърите, които искам да свържа. Опитвам се да стартирам това на perl скрипта:

my $cmd_gzip = "$source_dir -name \"$log_name_pattern\" -a ! -name \"*.gz\" -a ! -mtime -$archive_interval -a ! -size 0 -a -type f -exec gzip {} \\;";

system("ssh", "$source_user\@$source_server" , "find" , $cmd_gzip);

Той успешно се свързва с отдалечен сървър, изброявайки файловете. Но когато исках да архивирам файловете, които исках да архивирам, не работи. Конзолата казва „Разрешението е отказано“

Архивният модул, който е най-отгоре, има модул extract_files. Това е така:

sub extract_files
{
    Utilities::logger(Utilities::DEBUG,"Entering sub: extract_files");
    my $temp = shift;

    my $size = scalar(@$temp);
    Utilities::logger(Utilities::DEBUG,"Initial array size is $size.");
    my $temp_log_name_pattern = $log_name_pattern;
    $temp_log_name_pattern =~ s/\*/.*/g;

    my $i = 0;
    while($i < $size)
    {
        Utilities::logger(Utilities::DEBUG,"Currently processing: $$temp[$i]. i = $i, size = $size");
        # Extract only files from output. " character in second part is used to filter out initial find command that can wrap and exist in the output.
        if ($$temp[$i] =~ $temp_log_name_pattern and $$temp[$i] !~ m/.*".*/)
        {
            Utilities::logger(Utilities::DEBUG,"Matched filename: $$temp[$i]");
            $i++;
        }
        else
        {
            Utilities::logger(Utilities::DEBUG,"Did not match filename: $$temp[$i]");
            splice(@$temp,$i,1);
            $size--;
        }
    }
    Utilities::logger(Utilities::DEBUG,"Exiting sub: extract_files");
}

Мисля, че това кара скрипта да работи и избягва грешката „Разрешението е отказано“. Но получава параметър като този:

my $output = Utilities::run_remote_command_with_login($source_server, $cmd_list, $source_user, get_pwd($source_user));

    extract_files(\@$output);

Така че сега питам две неща,

  1. Не разбрах какво връща този модул run_remote_command_with_login, така че не мога да създам моя модул за ssh връзка, за да използвам всички модули правилно. Как мога да получа връщане от моята системна команда? като модула run_remote_command_with_login получи system("ssh", "$source_user\@$source_server" , "find" , $cmd_gzip);(не съм написал този модул)

  2. Ако греша, модулът extract_files() не работи за избягване на грешката „Отказано разрешение“. Как мога да го направя ? Има ли идеи.

Надявам се, че казах всичко, което искам да попитам истина. Благодаря ви предварително.


person Hayra    schedule 20.03.2014    source източник


Отговори (1)


Трябва да проверите дали потребителският акаунт за ZIPping има правилните разрешения. Може да се наложи да отпечатате потребителския акаунт, което под Linux може да стане с командата id.

person Mark Leighton Fisher    schedule 21.03.2014