我有一个远程脚本,可以使用ssh user@host "bash /path/to/remote/script.sh"
.
如果直接从远程 shell 执行此脚本,我不希望它运行,但仅当通过 SSH 在本地执行时才运行。我考虑过向脚本传递一个类似的值ssh user@host "bash /path/to/remote/script.sh local"
,并且脚本退出 if $1
was not local
,但是有没有更可靠的方法来测试这一点?
非常感谢,史蒂夫。
答案1
您可以检查脚本的父进程 pid 的进程名称是否匹配sshd
。
例如,在脚本早期的某个地方(紧接该#!
行之后是一个好地方):
#!/bin/bash
if [ "$(ps h -o comm -p "$PPID")" != "sshd" ] ; then
echo "This script can only be run directly from ssh." > /dev/stderr
exit 1
fi
这使用 bash 的内置只读变量“$PPID”。它在 bash 的每个实例中自动定义。
请注意,这是毫无意义的,因为任何具有脚本读取权限的人都可以复制它并删除这几行。无论脚本使用什么方法来尝试执行此操作,情况都是如此。
此外,进程名称很容易伪造。sshd
在运行脚本之前编写一个包装器脚本将其进程名称设置为 是很容易的。
如果您担心其他用户可能会运行您的脚本,您是否考虑过设置脚本的权限,以便仅有的脚本的所有者可以读取或执行它吗? (例如chmod 700 /path/to/script
)
答案2
一个相当糟糕的、低分辨率的方法是测试 SSH 会话变量是否存在:
SSH_CLIENT='10.10.11.11 48052 22'
SSH_CONNECTION='10.10.11.11 48052 10.20.30.40 22'
SSH_TTY=/dev/pts/2
但是,远程计算机上不受信任的用户可以轻松伪造此类变量,然后运行该脚本。
我能想到的确保脚本无法在远程计算机上的本机 shell 中运行的最佳方法是不在远程计算机上存储脚本。相反,请将其本地存储在您所在的计算机上ssh
:
ssh user@host bash < /local/path/to/script.sh
[编辑]
如果您想将远程脚本保留在调用它的本地脚本中(而不是在单独的文件中),则此处文档就足够了,例如本例中:
#/usr/bin/env bash
user='someuser'
host='remote.host.name'
ssh -T $user@$host << \EOF
printf 'The remote hostname is: '
hostname
printf 'Current time on the remote host is: '
date
EOF
您可以通过执行以下操作进一步划分远程脚本:
#/usr/bin/env bash
remote_script() {
cat << \EOF
printf 'The remote hostname is: '
hostname
printf 'Current time on the remote host is: '
date
EOF
}
user='someuser'
host='remote.host.name'
remote_script | ssh -T $user@$host