我需要编写一种方法来执行以下操作(请注意,所有这些都是在本地机器上以root身份完成的):
runuser -l user1 -c 'ssh localhost' &
runuser -l user1 -c 'systemctl --user list-units'
第一个命令应以 root 用户身份运行。最终目标是以"user1"身份登录,以便如果任何用户运行who
"user1"将显示在此列表中。注意到在运行下一个命令之前,第一个命令的后台设置方式。 下一个命令也应该以 root 身份运行,而不是以 user1 身份运行。
问题:这些命令在单独运行时运行良好,但在脚本中运行时,"user1"在运行who
时永远不会显示。这是我的脚本
#!/bin/bash
echo "[+] Becoming user1"
runuser -l user1 -c 'ssh -q localhost 2>/dev/null' &
echo
sleep 1
echo "[+] Running systemctl --user commands as root."
runuser -l user 1 -c 'systemctl --user list-units'
echo "[+] Killing active ssh sessions."
kill $(ps aux | grep ssh | grep "^user1.*" | grep localhost | awk '{print$2}') 2>/dev/null
echo "[+] Done."
运行脚本时,脚本看起来能够通过 ssh 进入系统,但who
不显示用户已登录,也没有任何ps aux
输出显示 ssh 会话。注意:我注释掉了kill
行以确认该过程是否仍然存在,但我根本没有看到它。 如何使 bash 脚本分叉两个进程。进程 1 的目标是以"user1"身份登录并等待。那么进程 2 是在用户 1 登录时以 root 身份执行命令?
我的目标是通过脚本以 root 身份运行 systemctl --user 命令。如果您熟悉systemctl --user domain,则无法管理系统ctl --用户单元,而无需通过传统方法(ssh,直接终端或gui)登录。我也不能"su - user1"作为根。所以我想通过 runuser 命令将 ssh 会话作为 root 强制给 vdns11 用户。一旦用户通过身份验证并显示,我就可以运行 systemctl --user 命令。如何在代码中保持 ssh 会话处于活动状态?
有了这些额外的信息,问题基本上可以归结为">如何启动交互式 ssh 会话并设置后台?
您可以使用script
。它可以用来诱使应用程序认为它们正在以交互方式运行:
echo "[+] Starting SSH session in background"
runuser -l user1 -c "script -c 'ssh localhost'" &>/dev/null &
pid=$!
...
echo "[+] Killing active SSH session"
kill ${pid}
OP之前的原始答案提供了更多详细信息(供将来参考):
让我们剖析一下这里发生了什么。
我假设你以 root 身份启动脚本:
echo "[+] Becoming user1"
runuser -l user1 -c 'ssh -q localhost 2>/dev/null' &
所以root
运行runuser -l user1 -c '...'
,它本身运行ssh -q localhost 2>/dev/null
user1
。由于&
,所有这些都发生在后台
。ssh
将打印Pseudo-terminal will not be allocated because stdin is not a terminal.
(由于2>/dev/null
而隐藏)并立即退出。这就是为什么您在运行who
或运行ps
时看不到任何内容的原因。
您的echo
显示[+] 正在成为用户 1,这与正在发生的事情完全不同。
sleep 1
脚本休眠一秒钟。这没什么不对。
echo "[+] Running systemctl --user commands as root."
#runuser -l user 1 -c 'systemctl --user list-units'
# ^ typo!
runuser -l user1 -c 'systemctl --user list-units'
忽略拼写错误,root
再次运行runuser
,它本身这次user1
运行systemctl --user list-units
。
您的echo
显示[+] 以 root 身份运行 systemctl --user 命令,但实际上您systemctl --user list-units
如上所述user1
运行。
echo "[+] Killing active ssh sessions."
kill $(ps aux | grep ssh | grep "^user1.*" | grep localhost | awk '{print$2}') 2>/dev/null
这将终止在脚本开始时启动的ssh
进程,但它已经退出,因此这不执行任何操作。作为旁注,这可以更容易地完成:
echo "[+] Becoming user1"
runuser -l user1 -c 'ssh -q localhost 2>/dev/null' &
pid=$!
...
echo "[+] Killing active ssh sessions."
kill $(pgrep -P $pid)
所以这应该让你更好地了解脚本的实际作用,但是在你描述的目标和脚本中相互冲突的echo
之间,真的很难弄清楚它应该去哪里。