我正在尝试在一个命令中运行以下两个命令。
eval "$(ssh-agent)"
ssh add ~/.ssh/id_rsa
我尝试了许多可能的解决方案:
su username -c "{ eval $(ssh-agent -s) }; ssh-add ~/.ssh/id_rsa"
su username -c "eval $(ssh-agent -s)" ; ssh-add ~/.ssh/id_rsa
su username -c "eval $(ssh-agent -s)" && ssh-add ~/.ssh/id_rsa
su username -c "eval $(ssh-agent -s)" && "ssh-add ~/.ssh/id_rsa"
第一个命令似乎成功运行,但第二个命令要么用Permission denied消息响应(意味着它与当前用户一起运行(,要么无法连接到身份验证代理(意味着可能为第二个指令创建了一个新会话(。
错误消息:
Could not open a connection to your authentication agent.
Error connecting to agent: Permission denied
如果我按顺序分别运行它们,它会起作用:///
目的是用这些带有变量的命令创建一个bash脚本,类似于以下内容:
folder=/home/q12
username=q12
su $username -c "{ eval $(ssh-agent -s) }; ssh-add $folder/.ssh/id_rsa"
由于变量的原因,我不能引用整个命令,因为它对"以及"&&";。
有人能帮我吗?非常感谢。
您需要单引号。否则,将在当前上下文中评估命令替换。
su username -c 'eval "$(ssh-agent -s)"; ssh-add ~/.ssh/id_rsa'
编辑:
要获得ssh-add
的条件执行,您可以执行:
su username -c 'script=$(ssh-agent -s) || exit 1; eval "$script"; ssh-add ~/.ssh/id_rsa'
# or
su username -c 'set -e; script=$(ssh-agent -s); eval "$script"; ssh-add ~/.ssh/id_rsa'
su -c STRING
中的参数是命令字符串,类似于bash -c STRING
。我们也可以在单引号中嵌套双引号。
您的第一次尝试最接近,但在双引号中,像$(ssh-agent -s)
这样的东西在作为参数传递给su
之前会由您的shell进行评估。最终结果:ssh代理在当前用户下运行,因此其他用户无法使用它
您需要将评估延迟到其他用户shell。使用单引号而不是双引号可以做到这一点,但在实际命令中,您有$folder
,您显然希望由您的shell进行评估(它不会在其他用户shell中定义(,因此不希望延迟评估。最简单的方法是转义要延迟评估的$
(您的shell将删除转义,因此其他用户shell将看到并评估它(:
su "$username" -c "eval $(ssh-agent -s); ssh-add $folder/.ssh/id_rsa"
# ^ Note the escape
(顺便说一句,我还在用户名周围加了双引号,因为这通常是很好的脚本卫生。引用$folder
更复杂,只要它不包含任何奇怪的字符,就没有必要,所以我跳过了它。此外,{ }
也没有必要,如果使用它们,}
之前需要有一个;
…所以我只是删除了它们。(
另一种选择是对命令的一部分进行单引号引用,对另一部分进行双引号引用(混合引号看起来很奇怪,但在shell语法中完全合法(:
su "$username" -c 'eval $(ssh-agent -s);'" ssh-add $folder/.ssh/id_rsa"
# ^ single-quoted part ^^ double-quoted part ^
其余尝试都无效的原因是命令(;
或&&
(之间的分隔符不在带引号的字符串中,因此被您的shell视为分隔符,因此第二个命令是在您的用户ID下运行的,而不是作为su
命令的一部分。