对于非 root 用户来说,使用不在系统 shell 列表中的可执行文件就像它是用户的实际 shell 一样,有什么好的方法吗?
我正在尝试使用两个不同版本的 bash 来执行此操作。旧版本是实际的 shell。它显示在 中chsh -l
,位于通常的/bin/bash
,并且是系统认为的我的 shell。我想要一个较新的版本来伪装成我的 shell。我已将其编译到目录中。现在我的 中有这个.bashrc
。
if [ $(echo $0) != $PATH_TO_NEW_SHELL_EXECUTABLE ]; then
export SHELL=$PATH_TO_NEW_SHELL_EXECUTABLE
exec "$SHELL" "$@"
fi
我遇到的问题是,在这台机器上通过 ssh 运行的命令会挂起exec
。rsync
也会scp
挂起。例如,以下内容将挂起。
ssh user@host false
我不明白这种行为。除此之外,这有效。我甚至可以顺利启动交互式 ssh 会话。
我怎样才能解决这个特定的问题?更一般地说,模拟正确安装的 shell 的最佳方法是什么?
答案1
当我尝试用 exec 替换登录 shell(用其他/新 shell)时,我丢失了 tty:
10869 1118 root 0.0 0.0 \_ sshd: username [priv]
10907 10869 username 0.0 0.0 | \_ sshd: username@notty
10908 10907 username 0.0 0.0 | \_ /bin/bash
这可能是问题所在。
答案2
它没有挂起。你的命令没有运行,但你的新 shell 就在这里,交互式的,没有提示
test@myhost:~$ ssh localhost false
test@localhost's password:
echo $0
/home/test/bin/myshell
echo $#
0
现在如果在 exec 之前的 .bashrc 中添加以下行:
echo $# "$0" "$@"
sleep 300
你可以看到发生了什么:
test@myhost:~$ ssh localhost false uselessparm1 uselessparm2
0 bash
旁:
|-sshd(25350)---sshd(18920)---sshd(18925)---bash(18926)---sleep(18927)
$ cat /proc/18926/cmdline |tr '\0' '\n'
bash
-c
false uselessparm1 uselessparm2
sshd 确实会运行bash -c 'false uselessparm1 uselessparm2'
但出于某种原因,在这种情况下,命令行参数存在,但 $1 $2 ... 未在 shell 中设置 ($#=0)。因此 exec 永远不会运行除新 shell 之外的任何其他程序
您应该将您的技巧放入 ~/.bash_profile(登录时执行)中,并保持 ~/.bashrc 不变。