我对 Linux 没有经验,但我每天都在学习。
我有这个命令。
ssh admin@$host mv repo/environments/qa/* /repo
这个*
字符是否意味着environments/qa
目录中的所有内容都将放入该/repo
目录中?如果它已经存在,它会取代它吗?
抱歉,我对 shell 命令缺乏经验。我只是想确认一下。
答案1
翻译成另一种语言:
ssh admin@$host mv repo/environments/qa/* /repo
shell 命令(假设是 POSIX shell,例如 sh 或 bash),如下所示:
execute("ssh", glob(split("admin@" + $host)), "mv", glob("repo/environments/qa/*"), "/repo");
(基于 的字符进行拆分$IFS
,但仅基于 扩展的部分$host
;就像 if $host
ismachine
和$IFS
contains一样an
,admin@machine
将被拆分为admin@m
, chi
, 和e
,字面量中的a
和不受拆分)。n
admin
虽然您希望它是:
execute("ssh", "admin@" + $host, "mv repo/environments/qa/* /repo")
shell 中的语法为:
ssh admin@"$host" 'mv repo/environments/qa/* /repo'
ssh
会将该mv repo/environment/qa/* /repo
字符串传递到sshd
远程服务器上,以便将其传递到远程用户的登录 shell 进行解释,通常为:
execute("that-shell", "-c", "mv repo/environments/qa/* /repo")
在大多数 shell 中,这相当于:
execute("mv", glob("repo/environments/qa/*"), "/repo")
告诉mv
移动所有非隐藏文件(任何类型,包括目录)内repo/environments/qa
(本身是相对于 shell 进程当前工作目录的路径,该进程sshd
应已初始化为用户的主目录)到/repo
1。
从中可以得出一些结论:
像上面这样的参数扩展
$host
几乎必须总是被引用以避免 split+glob。您希望远程系统上的 shell 扩展该 glob,因此
*
必须按字面传递。重要的是要记住,
ssh
远程解释 shell 代码并不运行简单的命令。如果传递多个参数,它将用空格将它们连接起来以组成要传递到远程 shell 的代码,但我建议您仅传递一个代码参数,如果只是为了提醒它是 shell 代码而不是简单的命令,并且远程 shell 语法中的任何特殊字符都将被视为此类字符。例如,不要 do
ssh host echo *.txt
,因为这*.txt
将由本地 shell 扩展,并且如果foo;reboot #.txt
当前工作目录中有一个文件被调用,那么这将导致execute("ssh", "host", "echo", "foo;reboot #.txt")
完成,然后sshd
运行execute("sh", "-c", "echo foo;reboot #.txt")
并重新启动。
¹ 请注意 if/repo
确实存在或不是类型目录(或目录的符号链接)并repo/environments/qa/*
扩展为仅一个文件,该文件将是重命名,搬去(相对于搬进)/repo
;更改/repo
为可以避免该问题,如果不是目录则/repo/
报告错误。/repo