我有一个想要开始的流程,但后来忘记了。同步运行时,看起来像
sudo -E lein run
这运行得很好,无限期。它是非交互式的。它在端口 80 启动一个 Web 服务器。但是当我运行时:
sudo -E lein run &
终端输出:
[4] 30236
几秒钟后:
[4] + 30236 suspended (tty input) sudo -E ../bin/lein run
我的进程应该在端口 80 启动 Web 服务器,但没有显示服务器。
问题: 我如何诊断发生了什么?我不认为标准输出和标准错误被打印,但我可能是错的。为什么进程会暂停?我可以lein run
以另一种方式异步运行吗?
答案1
该sudo
命令期望能够通过 tty 与用户交谈。当您将其推入后台时,它会停止,因为它期望对 tty 进行独占访问,但不再具有独占访问权限。 (这是一个安全界面,可能需要密码,并且肯定会运行对用户帐户具有不同访问权限的程序。重要的是它对用户具有独占访问权限。)
您可以在 下运行您的程序screen
,这给它一个虚拟 tty,不一定与“真实”tty 关联。
screen -md sudo -E lein run
答案2
后台进程无法从终端读取数据。如果它们尝试读取数据,则会被 SIGTTIN 暂停(t埃勒t类型在放)信号。这一功能的原因是,如果多个进程尝试从终端读取数据,则每个字符基本上会随机进入其中一个进程,这不是有用的行为。因此,前台进程获取输入,而后台进程则不获取输入。
(我简化了一点。阅读控制终端和终端访问控制如果您想要更精确的规范,但您很少会遇到需要比我上面写的更深入挖掘的情况。)
如果 sudo 尝试从终端读取数据以提示输入密码,它将被挂起。需要在前台运行sudo,然后切换到后台。
通常,您可以运行 shell,然后告诉它在后台执行命令。例如,对于su
,您会这样做su -c 'lein run &'
。但 sudo 的作者知道这是一个常见问题,因此有一个选项:将-b
选项传递给sudo
。
sudo -b -E lein run
类似地,ssh
您可以-f
在提示输入密码后使用进入后台。请注意,如果您这样做,您的后台进程将不再是 shell 作业。如果您想在后台运行该程序并忘记它,那就完美了。