Что возвращает эта системная команда?

У меня есть такой модуль. Прежде всего, я хочу объяснить все, что 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, это конфигурация 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