Использование запроса perl system () с пробелами в переменной пути - PullRequest
0 голосов
/ 22 февраля 2019

Кажется, я застрял здесь.Я хочу отправить системный запрос из моего скрипта на другой сервер через SSH, проверяя, существует ли там папка.Путь к папке передается из другого скрипта, хранится в переменной и может содержать пробел.Поскольку я не мог заменить пробел другим символом, чтобы избежать «не найденного» в папке типа «foo bar», мне нужно передать что-то вроде ls '/folderpath/foo bar' в оболочку другого сервера.Пример кода выглядит следующим образом:

$cmd = 'ssh -i id_pub $ssh_addr ls $remote_dir'; 
if (system($cmd) == 0) {
do something
}

Я исчерпал все возможные варианты - устал выходить из возможного пробела с помощью \ перед передачей его команде, пытался передать его с помощью '', "", внутрии добавив оба, прежде чем передать его в $ cmd.Но я всегда получаю что-то вроде этого:

ls \folderpath\foo\\ bar or ls \' \folderpath\foo bar\'

, но не ls '\folderpath\foo bar'

Я не так хорош в Perl, возможно, кто-то более опытный может порекомендовать обходной путь?

Ответы [ 4 ]

0 голосов
/ 23 февраля 2019

Пусть Net :: OpenSSH позаботится обо всем за вас:

my $ssh = Net::OpenSSH->new($ssh_addr);
$ssh->error and die "unable to connect to remote host: " . $ssh->error;
if ($ssh->test('test', '-d', $remote_dir)) {
   # do something here!
}

О, кажется, вы на Windows-машине!Вы можете использовать Net :: SSH :: Any там аналогичным образом.

0 голосов
/ 22 февраля 2019

Запуск локальной оболочки и использование ее для экранирования вашей команды для безопасности удаленной оболочки будет выглядеть следующим образом:

system('env', "ssh_addr=$ssh_addr", "remote_dir=$remote_dir", 'bash', '-c',
       'printf -v remote_cmd "%q " ls -- "$remote_dir"; ssh "$ssh_addr" "$remote_cmd"');

В отличие от простого использования "'$remote_cmd'", вышеприведенное работает со всеми возможными значениями,включая намеренно злонамеренные, при условии, что ваша удаленная оболочка также является bash.

Благодаря @ ikegami's answer за демонстрацию использования сигил конца-опций --чтобы гарантировать, что даже значение remote_dir, начинающееся с тире, будет проанализировано как позиционный аргумент с помощью ls

0 голосов
/ 22 февраля 2019

String :: ShellQuote shell_quote полезен при создании команд оболочки.

my $remote_cmd = shell_quote("ls", "--", $remote_dir);
my $local_cmd = shell_quote("ssh", "-i", "id_pub", $ssh_addr, $remote_cmd);
system($local_cmd);

Конечно, вы можете избежать оболочки на локальной стороне следующим образом:

use String::ShellQuote qw( shell_quote );

my $remote_cmd = shell_quote("ls", "--", $remote_dir);
system("ssh", "-i", "id_pub", $ssh_addr, $remote_cmd);
0 голосов
/ 22 февраля 2019

ОК, у вас есть несколько возможностей расширения оболочки в зависимости от того, как вы это делаете.

Во-первых, вы используете system () со строкой.Это сломает все ваши пути на космические символы.Вы можете решить эту проблему, используя систему в виде списка

system('ssh', '-i', 'id_pub', $ssh_addr, 'ls', $remote_dir)

Теперь у нас все еще есть проблема, так как ssh запустит удаленный код на удаленном сервере в оболочке с расширением оболочки, что приведет к пробелу в пробелах снова

Так что вам нужно поместить $ remote_dir внутри ' символов, чтобы не дать удаленной оболочке разбить путь: давая

system('ssh', '-i', 'id_pub', $ssh_addr, 'ls', "'$remote_dir'")

Надеюсь, это поможет / работает

Обратите внимание, что, как сказали ниже комментаторы, это предполагает, что в $ remote_dir нет символов '.Вам нужно либо экранировать, либо анализировать $ remote_dir, чтобы убедиться, что вы не получите путь, похожий на /file.txt'; rm -rf / #, который попытается удалить каждый файл в удаленной системе

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...