如何解决 rsync 的错误“execv:没有此文件或目录”?
我正在尝试使用 rsync 将多台机器备份到 Linux 服务器,并且它在大多数情况下都有效:
- 服务器本身的路径到路径 rsync 备份
- 在服务器上使用 rsync 从运行 cygwin-rsyncd 的 Windows 远程服务器获取文件
不起作用的是使用 rsync-via-ssh 备份我的 Android 手机(运行 SimpleSSHD)。至少,不是以任何由服务器启动的方式,这是我的目标。
- 服务器:Gentoo Linux,主机名“crucible”,ip 192.168.7.94
- 手机:HTC One M8 上的 LineageOS,主机名“rondel”,ip 192.168.7.33
下面对什么有效、什么无效以及如何进行分析。
- 在服务器上,打开 ssh 进入手机,然后从那里打开 ssh 返回服务器:成功了
aeheathc@crucible ~ $ ssh -i /home/aeheathc/.ssh/id_rsa -p 2222 -l backuppc rondel
:/ # ls
[phone file listing]
:/ # ssh -i /data/smbrw_key -p 22 -l smbrw 192.168.7.94
Could not create directory '/.ssh'.
The authenticity of host '192.168.7.94 (192.168.7.94)' can't be established.
ECDSA key fingerprint is SHA256:[random stuff here].
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Failed to add the host to the list of known hosts (/.ssh/known_hosts).
smbrw@crucible ~ $ ls
[local server file listing]
- 在服务器上,通过 ssh 使用 rsync 从手机获取文件:错误,“execv:没有这样的文件或目录”
aeheathc@crucible ~ $ rsync -a --progress --delete -e "ssh -i /home/aeheathc/.ssh/id_rsa -p 2222" backuppc@rondel:/storage/emulated/0/ /backup/redundinator/hosts/rondel/paths/_storage_emulated_0
execv: No such file or directory
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: error in rsync protocol data stream (code 12) at io.c(228) [Receiver=3.2.3]
- 在手机上,使用 rsync 通过其 rsyncd 将文件推送到服务器:有效
aeheathc@crucible ~ $ ssh -i /home/aeheathc/.ssh/id_rsa -p 2222 -l backuppc rondel
:/ # rsync -a --progress --delete --password-file=/storage/emulated/0/rsync_backup_crucible /storage/emulated/0/ rsync://[email protected]/backup/redundinator/hosts/rondel/paths/_storage_emulated_0
sending incremental file list
[normal rsync progress output]
- 在手机上,使用 rsync 通过 ssh 将文件推送到服务器:有效
aeheathc@crucible ~ $ ssh -i /home/aeheathc/.ssh/id_rsa -p 2222 -l backuppc rondel
:/ # rsync -a --progress --delete -e 'ssh -i /data/smbrw_key -p 22' /storage/emulated/0/ [email protected]:/mnt/backup/redundinator/hosts/rondel/paths/_storage_emulated_0
Could not create directory '/.ssh'.
The authenticity of host '192.168.7.94 (192.168.7.94)' can't be established.
ECDSA key fingerprint is SHA256:[random stuff here].
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Failed to add the host to the list of known hosts (/.ssh/known_hosts).
sending incremental file list
[normal rsync progress output]
- 在服务器上,使用打开 ssh 到手机并在那里运行命令将文件 rsync 回服务器的命令(连接到 rsyncd 或 ssh):错误,“execv:没有这样的文件或目录”
aeheathc@crucible ~ $ ssh -i /home/aeheathc/.ssh/id_rsa -p 2222 -l backuppc rondel "rsync -a --progress --delete --password-file=/storage/emulated/0/rsync_backup_crucible /storage/emulated/0/ rsync://[email protected]/backup/redundinator/hosts/rondel/paths/_storage_emulated_0"
execv: No such file or directory
aeheathc@crucible ~ $ ssh -i /home/aeheathc/.ssh/id_rsa -p 2222 -l backuppc rondel "rsync -a --progress --delete -e 'ssh -i /data/smbrw_key -p 22' /storage/emulated/0/ [email protected]:/mnt/backup/redundinator/hosts/rondel/paths/_storage_emulated_0"
execv: No such file or directory
- 在服务器上,使用打开 ssh 到手机的命令并在那里运行命令来回显文本:WORKS
aeheathc@crucible ~ $ ssh -i /home/aeheathc/.ssh/id_rsa -p 2222 -l backuppc rondel "echo blah"
blah
- 据我了解,错误是 execv 表示在传递给它的路径上找不到可执行文件。但那条路径是什么?我需要知道这一点才能自己进一步调查。
- /var/log/auth.log 仅包含成功的连接,没有任何启发性信息。
- 任何命令之前使用 sudo 似乎都没有帮助。
答案1
可能发生的情况是,当你ssh
直接进入手机时,PATH
会被完全填充并包含 的路径rsync
。然而,在不同场景下运行不同的初始化文件(例如/etc/profile
,,,~/.profile
)~/.bashrc
。如果运行ssh «destination» -- «command»
,ssh
则以非交互模式运行 shell。这似乎意味着配置文件脚本不会运行,只有 rc 脚本会运行。对于bash
,这意味着~/.bashrc
运行~/.bash_profile
而不运行。看看这个输出对我来说有何不同:
ohnobinki@gibby ~ $ ssh localhost -- "echo \${PATH}"
/usr/bin:/bin:/usr/sbin:/sbin
ohnobinki@gibby ~ $ ssh localhost -- "sh -lc \"echo \\\${PATH}\""
/usr/x86_64-pc-linux-gnu/gcc-bin/9.1.0:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin:/usr/games/bin
该-l
选项要求sh
将 shell 视为登录会话,包括采购/etc/profile
和其他内容。
您也许可以执行以下操作之一:
指定(在正常交互式会话中
--rsync-path=/path/to/rsync
发现使用)如下:which rsync
ssh
rsync -a --progress --delete -e "ssh -i /home/aeheathc/.ssh/id_rsa -p 2222" --rsync-path=/usr/local/bin/rsync backuppc@rondel:/storage/emulated/0/ /backup/redundinator/hosts/rondel/paths/_storage_emulated_0
这种方法很容易理解。但是,感觉有点恶心。运行命令的人不应该
rsync
知道rsync
在手机上安装的位置——这会破坏封装。它也更脆弱,因为如果手机上的路径rsync
发生变化,这个命令也需要更新。使用更多的引用并让 shell 运行其交互式初始化,该初始化应该进入
rsync
路径(是的,我输入了rsync
两次,--rsync-path
因为sh -c
让您指定argv[0]
,所以我必须提供它以避免argv[1]
被吞噬):rsync -sa --progress --delete -e "ssh -i /home/aeheathc/.ssh/id_rsa -p 2222" --rsync-path="sh -lc \"rsync \\\"\\\${@}\\\"\" rsync" backuppc@rondel:/storage/emulated/0/ /backup/redundinator/hosts/rondel/paths/_storage_emulated_0
这个选项更加令人困惑和棘手,但对我来说似乎更好。这样,我们可以让手机知道它的
rsync
位置,而不是服务器上运行的命令。它似乎尊重封装,并且不那么脆弱/更通用。或者编辑您手机上的或等效文件以添加包含的
.bashrc
必要路径,而不仅仅是在配置文件脚本中指定它。rsync
PATH
这种方法感觉有点丑陋,因为不同 rc/profiles 应该做什么的约定表明
.bashrc
不应该设置环境变量,而应该做一些轻量级的事情并由登录 shell 启动。不幸的是,ssh
在制定这些约定时,似乎没有考虑到远程启动非交互式 shell 的方式。请注意,.bashrc
运行很多次,因此您应该小心不要盲目地附加PATH
——您最终可能会得到一个不必要的长文件PATH
,希望这不会造成任何损害,但可能会浪费资源或在某些极端情况下导致问题。