【发布时间】:2017-08-01 04:30:19
【问题描述】:
我在 Alpine docker 容器中运行 ruby(如果重要的话,它是一个 sidekiq 工作者)。在某个时刻,我的应用程序接收到指令以发送到子命令。我需要能够流式传输 STDOUT 而不是让它缓冲。这就是我使用 PTY 而不是 system() 或其他类似答案的原因。我正在执行以下代码行:
stdout, stdin, pid = PTY.spawn(my_cmd)
当我连接到 docker 容器并运行 ps auxf 时,我看到了:
root 7 0.0 0.4 187492 72668 ? Sl 01:38 0:00 ruby_program
root 12378 0.0 0.0 1508 252 pts/4 Ss+ 01:38 0:00 \_ sh -c my_cmd
root 12380 0.0 0.0 15936 6544 pts/4 S+ 01:38 0:00 \_ my_cmd
注意 ruby 的子进程是“sh -c my_cmd”,它本身有一个子“my_cmd”进程。
“my_cmd”可能需要很长时间才能运行。它被设计成向进程发送信号 USR1 会导致它保存其状态,以便稍后可以恢复并干净地中止。
问题是“PTY.spawn()”返回的 pid 是“sh -c my_cmd”进程的 pid,而不是“my_cmd”进程。所以当我执行时:
Process.kill('USR1', pid)
它将 USR1 发送到 sh,而不是 my_cmd,因此它的行为不正常。
有什么方法可以得到与我实际指定的命令相对应的 pid 吗?我对 PTY 领域之外的想法持开放态度,但它需要满足以下限制:
1) 我需要能够在写入时从 STDOUT 和 STDERR 流式输出,而无需等待它们被刷新(因为 STDOUT 和 STDERR 在 PTY 中混合在一起成为单个流,我正在重定向 STDERR到文件并使用 inotify 获取更新)。
2) 我需要能够将 USR1 发送到进程才能暂停它。
【问题讨论】: