3

我正在尝试expect在 Perl 脚本中使用系统调用来递归地在远程服务器上创建目录。相关调用如下:

system("expect -c 'spawn  ssh  $username\@$ip; expect '*?assword:*' {send \"$password\r\"}; expect '*?*' {send \"mkdir -p ~/$remote_start_folder/$remote_folder_name/$remote_username/$remote_date/\r\"}; expect '*?*' {send \"exit\r\"};  interact;'");

这工作正常。但是,如果是第一次使用 访问远程机器ssh,它会要求(yes/no)确认。我不知道在上面的声明中添加到哪里。有没有办法将它合并到上述语句中(使用某种or-ing)?

4

2 回答 2

5

将匹配项添加到与密码匹配yes/no项相同的调用中:expect

expect '*yes/no*' {send "yes\r"; exp_continue;} '*?assword:*' {send \"$password\r\"};

这将寻找两个匹配项,如果yes/no遇到exp_continue告诉期望继续寻找密码提示。

完整示例:

system( qq{expect -c 'spawn  ssh  $username\@$ip; expect '*yes/no*' {send "yes\r"; exp_continue;} '*?assword:*' {send "$password\r"}; expect '*?*' {send "mkdir -p ~/$remote_start_folder/$remote_folder_name/$remote_username/$remote_date/\r"}; expect '*?*' {send "exit\r"};  interact;'} );

我也习惯于qq避免逃避所有的引用。从带有-d标志的 shell 运行此命令显示期望查找任一匹配项:

Password: 
expect: does "...\r\n\r\nPassword: " (spawn_id exp4) match glob pattern
    "*yes/no*"? no
    "*?assword:*"? yes

提示yes/no

expect: does "...continue connecting (yes/no)? " (spawn_id exp4) match glob pattern
    "*yes/no*"? yes
...
send: sending "yes\r" to { exp4 }
expect: continuing expect
...
expect: does "...\r\nPassword: " (spawn_id exp4) match glob pattern
    "*yes/no*"? no
    "*?assword:*"? yes
...
send: sending "password\r" to { exp4 }
于 2013-10-07T10:09:05.653 回答
2

你不必要地使你的生活复杂化。

如果您想从 Perl 获得类似期望的功能,只需使用Expect模块。

如果您想通过 SSH 与某个远程服务器交互,请使用 CPAN 提供的一些 SSH 模块:Net::OpenSSHNet::SSH2Net::SSH::Any

如果您不想确认远程主机密钥,请将选项传递StrictHostKeyChecking=no给。ssh

例如:

use Net::OpenSSH;

my $ssh = Net::OpenSSH->new($ip, user => $username, password => $password,
                            master_opts => [-o => 'StrictHostKeyChecking=no']);

my $path = "~/$remote_start_folder/$remote_folder_name/$remote_username/$remote_date";
$ssh->system('mkdir -p $path')
    or die "remote command failed: " . $ssh->error;
于 2013-10-09T07:49:34.897 回答