You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bash脚本实现user1后台SSH登录并以Root执行命令的问题排查与解决方案咨询

解决Bash脚本中无法让user1保持SSH登录的问题

首先,先梳理你脚本里的明显问题,再分析核心原因和对应的解决方案:

1. 脚本中的拼写错误

你的脚本里有个低级笔误:runuser -l user 1 -c 'systemctl --user list-units'这里的user 1多了空格,应该是user1。这个错误会直接导致这条命令执行失败,虽然不是who看不到登录的核心原因,但必须先修正。

2. 核心问题:SSH会话无TTY且易被进程组回收

当你在脚本后台执行runuser -l user1 -c 'ssh localhost' &时,存在两个致命问题:

  • 缺少TTY终端:脚本运行在非交互式环境下,没有分配终端(TTY)。而SSH的交互式登录必须依赖TTY才能保持会话,单独执行命令时你是在终端里操作,所以有TTY支持,SSH能正常留存;但脚本后台运行时没有TTY,SSH启动后会立刻退出。
  • 进程组信号终止:即使SSH侥幸启动,当runuser的父进程(脚本)继续运行或结束时,后台的SSH进程会因为属于同一个进程组,收到SIGHUP信号被强制终止,哪怕你用了&后台运行。

3. 解决方案:强制分配TTY并隔离进程

要让user1的SSH会话稳定留存,需要给SSH强制分配TTY,同时让进程脱离脚本的进程组,避免被回收。下面是修正后的完整脚本:

#!/bin/bash
set -euo pipefail

# 启动持久化SSH会话:强制分配TTY,用nohup脱离脚本进程组
echo "[+] Starting persistent SSH session for user1"
nohup runuser -l user1 -c 'ssh -t -t -q localhost 2>/dev/null' >/dev/null 2>&1 &
# 延长等待时间,确保SSH会话完全建立
sleep 2

echo "[+] Running systemctl --user commands as root"
# 修正拼写错误:user1而非user 1
runuser -l user1 -c 'systemctl --user list-units'

# 如果你不需要长期保持登录,可以取消下面两行的注释来终止SSH会话
# echo "[+] Killing active ssh sessions"
# pkill -u user1 ssh

echo "[+] Done"

关键修改点说明

  • ssh -t -t:强制分配TTY,即使在非交互式环境下也能让SSH保持交互式登录状态,这样who命令才能识别到这个会话。
  • nohup ... >/dev/null 2>&1 &:用nohup让SSH进程脱离脚本的控制终端,避免脚本结束时发送SIGHUP信号终止进程;同时重定向所有输出到/dev/null,避免生成冗余的nohup.out文件。
  • 延长等待时间:把sleep 1改成sleep 2,给SSH足够的时间完成会话建立,避免后续的systemctl命令在会话未就绪时执行。

4. 验证方法

运行脚本后,执行who命令,你应该能看到类似user1 pts/0 2024-05-20 10:00 (:0)的条目,其中pts/0就是SSH会话分配的TTY。如果要确认进程,执行ps aux | grep user1 | grep ssh就能看到对应的SSH进程。

5. 额外注意事项

  • 确保user1已经配置了本地SSH免密登录(比如~user1/.ssh/authorized_keys中添加了自己的公钥),否则SSH会要求输入密码,脚本因无交互会直接失败。
  • 如果你需要who一直显示user1登录状态,就不要执行kill命令;如果只是测试用,完成操作后再终止会话即可。

内容的提问来源于stack exchange,提问作者Dave

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 19:32:35