我有一个Perl脚本执行此操作:它在我的系统上生成一个ssh身份验证密钥,然后将此密钥复制到远程Linux系统以进行无密码ssh连接 . 代码如下:
# Generate an rsa key and store it in the given file
system("ssh-keygen -t rsa -N '' -f /root/.ssh/id_rsa 1>/dev/null");
# Copy the generated key to a remote system whose username
# is stored in variable $uname and IP address is stored in variable $ip
system("ssh-copy-id -i /root/.ssh/id_rsa.pub $uname\@$ip 2>&1 1>/dev/null");
我遇到的问题是: ssh-copy-id
命令需要相当长的时间才能将密钥复制到远程系统 . 因此,当运行此Perl脚本时,它将显示为脚本已挂起 .
因此,我想显示“进度消息”:当副本正在进行时,我想显示“SSH身份验证密钥副本正在进行”,如果副本失败,则显示“无法复制”,如果成功,显示“复制成功” .
我该怎么做呢?
还有一个(根据Chas的回答):
我按照Chas的建议尝试了代码
死"could not fork: $!"除非定义(我的$ pid = fork);
#child sleeps然后以随机退出代码退出
除非($ pid){
print "Connecting to server "; exec "ssh-copy-id -i /root/.ssh/id_rsa.pub $uname@$ip 2>&1 1>/dev/null";
exit int rand 255;
}
#parent等待孩子完成
$ | = 1;
print "waiting: ";
我的@throbber = qw / . o O o . /;
直到($ pid = waitpid(-1,WNOHANG)){
#get下一帧
我的$ frame = shift @throbber;
#display it
print $frame;
#put在帧列表的末尾
推@throbber,$ frame;
#wait a quarter second
select undef, undef, undef, .25;
#backspace over the frame
print "\b";
}
问题是这样的:
现在,ssh-copy-id在连接到远程服务器时要求输入密码 . 因此,"throbber"输出(即显示的不同大小的圆圈)出现在密码输入之后,看起来很奇怪 . 这是它的样子:
当前输出
连接到远程服务器o0O0o #This是throbber . 输出没有打印动态改变输出,我可以
密码:o0O0oXXXXXo0O0o#你说对了,笨蛋也不必在密码提示下来了
我想要的输出:
连接到远程服务器o0O0o #Throbber应该只在这里显示,无论如何
密码:XXXXX
任何想法,任何人?
3 回答
在主进程让用户知道事情没有停止发生的情况下,分叉另一个进程来为你工作是相当简单的:
system()返回等待调用返回的程序的退出状态 . 如果系统调用成功,则不返回任何内容 .
因此你可以看到这样的代码:
这是非常不直观的;-)
我通常会做以下事情:
但是,如果你看一下perldoc,你会发现一个更好的选择:
我会选择这种方法 . 但是,如果不提及Perl Best Practices书中建议的方法,我会感到很高兴:
但请注意PBP recommendation list指向您使用autodie:
所以这可能是未来的规范方式 .
我不认为可以通过简单的方式(不使用分叉,定时器和诸如此类)将进度条添加到通过system()运行的单个外部命令,该命令不会生成输出 .
另一方面,我认为你的ssh-copy-id需要很长时间才能完成的原因是因为一个不合适的DNS设置(检查服务器端的sshd日志是否有线索) . ssh服务器可能会尝试解析客户端IP的反向映射并超时 . 修复这可能会加速很多事情 .
说到你的消息 . 你不能在运行system()命令之前使用打印,并使用系统的返回值来打印完成消息(正如其他一些答案所建议的那样)?