Expect脚本执行Rsync报错“No such file or directory”问题求助
解决rsync+expect脚本中通配符失效的问题
问题现象
用rsync更新远程机器多目录时,为避免重复输入密码,编写了expect脚本实现自动输密。单独执行rsync命令可正常同步,但运行脚本时出现错误:
Remote password: spawn rsync -rv /home/john/TestDir/* jim@192.168.0.20:/home/jim/TestDir (jim@192.168.0.20) Password: building file list ... rsync: [sender] link_stat "/home/john/TestDir/*" failed: No such file or directory (2) done sent 17 bytes received 20 bytes 74.00 bytes/sec total size is 0 speedup is 0.00 rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1338) [sender=3.2.7]
原脚本内容:
#!/usr/bin/expect -d read -s -p "Remote password: " PW echo "" expect <<EOF spawn rsync -rv /home/john/TestDir/* jim@192.168.0.20:/home/jim/TestDir expect "assword:" send "$PW\r" expect eof EOF
问题原因
单独执行rsync时,*通配符由bash shell负责展开,会替换成/home/john/TestDir/下的所有文件和目录;但在expect的spawn命令中,通配符不会被shell解析,rsync会把*当成一个具体文件名查找,因此报错。
解决方案
方案1:让bash处理通配符
将rsync命令放在bash -c中执行,让bash先解析通配符再运行rsync:
#!/usr/bin/expect -d read -s -p "Remote password: " PW echo "" expect <<EOF spawn bash -c "rsync -rv /home/john/TestDir/* jim@192.168.0.20:/home/jim/TestDir" expect "assword:" send "$PW\r" expect eof EOF
方案2:直接同步目录内容(更推荐)
如果需要同步目标目录下所有内容,直接指定目录路径并加上末尾的/,rsync会自动同步目录内所有文件,无需通配符:
#!/usr/bin/expect -d read -s -p "Remote password: " PW echo "" expect <<EOF spawn rsync -rv /home/john/TestDir/ jim@192.168.0.20:/home/jim/TestDir expect "assword:" send "$PW\r" expect eof EOF
注意:目录末尾的
/很关键——不加的话,rsync会把TestDir目录本身同步到远程的/home/jim/TestDir下,形成/home/jim/TestDir/TestDir;加上/则是同步TestDir内的所有内容到远程的/home/jim/TestDir目录中。
更优替代方案:SSH密钥登录
相比expect脚本,SSH密钥登录更安全稳定,且无需脚本即可实现无密访问:
- 生成SSH密钥对:
执行后一路回车即可,按需设置密钥密码。ssh-keygen -t ed25519 - 将公钥复制到远程机器:
输入一次远程密码后,后续rsync或SSH连接都无需再输密码。ssh-copy-id jim@192.168.0.20
内容的提问来源于stack exchange,提问作者tkow
相关产品推荐
相关产品推荐

