2013-10-07 52 views
2

我試圖使用expect在Perl腳本中使用系統調用以遞歸方式在遠程服務器上創建目錄。相關電話如下:在系統中使用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)?

回答

3

添加yes/no匹配的expect同一調用作爲密碼匹配:

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

這將尋找兩場比賽,如果yes/no遇到exp_continue告訴Expect繼續尋找密碼提示。

完整的示例:

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

你是你的生命不必要地複雜。

如果您想要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;