我正在尝试使用Perl脚本中的系统调用expect
以递归方式在远程服务器上创建目录。相关电话如下:
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)?
答案 0 :(得分:3)
将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 }
答案 1 :(得分:1)
你不必要地使你的生活变得复杂。
如果你想要Perl的类似功能,只需使用Expect模块。
如果您想通过SSH与某个远程服务器进行交互,请使用CPAN提供的一些SSH模块:Net::OpenSSH,Net::SSH2,Net::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;