简体   繁体   中英

Using expect in Perl with system()

I am trying to use expect using system calls in a Perl script to recursively create directories on a remote server. The relevant call is as follows:

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;'");

This works fine. However, if it is the first time that the remote amchine is accessed using ssh , it asks for a (yes/no) confirmation. I don't know where to add that in the above statement. Is there a way to incorporate it into the above statement(using some sort of or -ing)?

Add a yes/no match to the same invocation of expect as the password match:

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

This will look for both matches, if yes/no is encountered exp_continue tells expect to keep looking for the password prompt.

Full example:

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;'} );

I've also used qq to avoid having to escape all the quotation. Running this command from a shell with -d flag shows expect looking for either match:

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

With yes/no prompt:

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 }

You are complicating your life unnecessarily.

If you want expect-like functionality from Perl, just use the Expect module.

If you want to interact with some remote server via SSH, use some of the SSH modules available from CPAN: Net::OpenSSH , Net::SSH2 , Net::SSH::Any .

Pass the option StrictHostKeyChecking=no to ssh if you don't want to confirm the remote host key.

For instance:

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM