我可以访问我无法完全控制的远程服务器,并且更喜欢让我的自动化脚本在本地运行该服务器上的操作。我发现并非所有使用 ssh 内联执行的命令的行为都相同。在 cron 作业中运行的示例:
ssh [email protected] "mysqldump -u dbuser -p'pass$word' dbname > backup.sql"
上述(及其许多变体)返回mysqldump: Got error: 1045: Access denied for user 'dbuser'@'localhost' (using password: YES) when trying to connect
.但我已经ssh
通过服务器验证了密码是否正确,然后手动运行mysqldump -u dbuser -p'pass$word' dbname > backup.sql
,一切正常。
另一个例子是运行类似的东西:
ssh [email protected] history > history.txt
上面的输出是空的,但是如果我ssh
到另一台机器然后手动运行history > history.txt
,输出是预期的。
如果我执行类似以下操作,一切都会按预期进行:
ssh [email protected] ls > ls.txt
我知道我可以mysqldump
通过省略并使用概述的-p'pass$word'
本地文件来绕过该示例.my.cnf
这里。并且history
可以找到专门的答案这里。
但我最终仍然会遇到另一个命令,即使我在内联运行和本地重定向输出时将它们包含在引号中,该命令也无法按预期工作。就好像 shell 正在读取附加了不同变量的内容,具体取决于它的访问方式。
如何执行内联 ssh 的任何命令,就好像我手动键入它但直接输出到本地计算机一样?
答案1
问题是你的报价:
$ word='phrase'
$ echo "pass$word"
passphrase
$ echo "'pass$word'"
'passphrase'
$ echo "'pass\$word'"
'pass$word'
强引号不会“保护”弱引号内的变量,因为它们会失去其神奇的属性。
一个简单的解决方案是逃避美元符号,这可能是你的失败:
$ ssh [email protected] "mysqldump -u dbuser -p'pass\$word' dbname > backup.sql"
另一种方法是将密码实际放入变量中:
$ password='pass$word' ssh [email protected] "mysqldump -u dbuser -p '$password' dbname > backup.sql"
第三,如果您想将备份转移到本地主机,请使用 SSH 隧道:
$ ssh -L 3306:localhost:3306 sleep 60 &
$ mysqldump -u dbuser -p 'pass$word' -h localhost -P 3306 dbname > backup.sql
此外,您的问题涉及将输出重定向到本地计算机,但您的命令不执行此操作:
$ ssh user@host "echo hello > output" # creates output on remote host
$ ssh user@host "echo hello" > output # creates output on local host