如何使用 bash 脚本在远程机器上运行命令?

Posted

技术标签:

【中文标题】如何使用 bash 脚本在远程机器上运行命令?【英文标题】:How to run commands on remote machine using bash script? 【发布时间】:2016-11-01 03:41:19 【问题描述】:

我正在尝试在远程机器上运行以下命令,但没有执行任何操作,谁能指出以下脚本的问题?

仅供参考,settings.yml 和 fuscation_util.rb 文件存在于testuser 帐户中

脚本:

sshpass -p "PASSWORD" ssh -o StrictHostKeyChecking=no -T root@HOSTNAME <<EOF
    su - testuser
    NEWLINE=$'\n'
    read -s -p "Enter Presto Password:$NEWLINE" VD_PASSWORD
    KEY=`cat settings.yml |grep '^key:'|sed 's/^key: //'`
    VALUE=`ruby fuscation_util.rb encrypt  "$KEY" "$VD_PASSWORD"`
    echo "$VALUE"
EOF

输出:

cat: settings.yml: No such file or directory
ruby: No such file or directory -- fuscation_util.rb (LoadError)

只有当我尝试将 poutput 分配给某个变量时,我才会遇到错误,使用下面的脚本我没有收到任何错误

脚本:

sshpass -p "PASSWORD" ssh -o StrictHostKeyChecking=no -T root@HOSTNAME <<EOF
    su - testuser
    NEWLINE=$'\n'
    read -s -p "Enter Presto Password:$NEWLINE" VD_PASSWORD
    cat settings.yml |grep '^key:'|sed 's/^key: //'
    ruby fuscation_util.rb encrypt  "testvalue" "testpassword"
EOF

输出:

WORKING FINE

【问题讨论】:

尝试将确切的路径添加到文件 w.r.t root user。 @Shravan40 - 这是一个很好的建议 - 介意我将其作为第二个选项添加到我的答案中吗? @Lix : 请补充。 我想指出一些你可以改变/改进的事情。 1. 我认为在 ssh 脚本中执行 read 和获取 VD_PASSWORD 没有任何意义。您可以从外部执行并将其传入。 2. 正如其他人所建议的那样,对 settings.yml 和 fuscation_util.rb 使用绝对路径 cat: /opt/settings.yml: 没有这样的文件或目录 ruby​​: 没有这样的文件或目录 -- /opt/fuscation_util.rb (LoadError) 使用绝对路径也会出现同样的错误 【参考方案1】:

我相信因为您是以 root 身份连接,所以您在连接时登陆的目录是 root 用户主目录。即使您更改了用户,您仍然会在同一个起始文件夹中(可能是/root)。

如果您在执行命令之前明确cd 到所需位置,您将可以访问所需文件。

另一个选项 (suggested by Shravan40) 是指定要处理的文件的绝对路径。


还应该提到的是,允许通过 SSH 进行 root 访问被认为是一种安全风险。我建议尽可能避免这种情况。

【讨论】:

cat: /opt/settings.yml: 没有这样的文件或目录 ruby​​: 没有这样的文件或目录 -- /opt/fuscation_util.rb (LoadError) 使用绝对路径也会出现同样的错误 您说“文件存在于 testuser 帐户中”是位于 /opt 文件夹中的 testuser 帐户吗?您确定这是文件的正确路径吗? 是的,我们已授予 testuser 访问 opt 目录的权限,仅供参考,我们的服务器架构完全不同,我们所有的服务器仅供内部使用 我不是指权限 - 错误表明找不到文件。您确定所需的文件在 /opt 文件夹中吗? 文件存在,只有当我尝试将输出分配给变量时才会出现错误,如果我删除分配,那么一切正常【参考方案2】:

一旦您的 ssh 以 root 身份连接到远程主机,它就会转到根目录。所以尝试更改目录或提供文件的绝对路径。

尽管远程运行命令存在安全风险。可能你可以在远程主机上放置一个脚本并传递参数,而不是在 ssh 中使用 echo。

更新:

只需在 ssh 之前进行所有赋值,并在调用 ruby​​ 时使用键值作为表达式。

试试这个:

read -s -p "Enter Presto Password:$NEWLINE" VD_PASSWORD
sshpass -p "PASSWORD" ssh -o StrictHostKeyChecking=no -T root@HOSTNAME <<EOF
su - testuser
cat settings.yml |grep '^key:'|sed 's/^key: //'
ruby fuscation_util.rb encrypt  `cat settings.yml|grep '^key:'|sed 's/^key: //'` $VD_PASSWORD
EOF

【讨论】:

cat: /opt/settings.yml: 没有这样的文件或目录 ruby​​: 没有这样的文件或目录 -- /opt/fuscation_util.rb (LoadError) 使用绝对路径也会出现同样的错误 "/opt/settings.yml: no such file" 因为该命令是在本地机器上执行的,而不是在远程服务器上。确认 cd 到不同的目录,如 /tmp 并查看 /opt/settings.yml 如何变为 /tmp/settings.yml。【参考方案3】:

除了使用完整路径以及您需要将&lt;&lt;EOF 替换为&lt;&lt;'EOF' 或所有反引号将在它们发送到远程端之前在调用端进行处理。

【讨论】:

我已经试过了,当我用'EOF'替换时,变量赋值不起作用

以上是关于如何使用 bash 脚本在远程机器上运行命令?的主要内容,如果未能解决你的问题,请参考以下文章

当我中断 ssh 本身时,如何使 ssh 杀死远程进程?

如何创建一个 bash 脚本来检查 SSH 连接?

如何使用SSH在远程计算机上运行shell脚本?

如何使用 Bash 脚本中的密码运行 sftp 命令?

如何从 bash 获取 telnet 命令的输出?

如何使用 ssh 在后台运行命令并分离会话