程序在後台啟動之前被殺死
我正在使用
script.sh
包含命令的 bash 腳本cmd
,在後台啟動:#!/bin/bash … cmd & …
如果我打開終端模擬器並執行
script.sh
,cmd
則按預期在後台正確執行。也就是說,雖然script.sh
已經結束,但cmd
繼續在後台執行,PPID 為 1。但是,如果我從前一個(或在桌面會話開始時,這是我的真實案例)打開另一個終端仿真器(比如說 xfce4-terminal),並
script.sh
執行xfce4-terminal -H -x script.sh
cmd
不再正確執行:它被script.sh
. 使用nohup
來防止這種情況是不夠的。我有義務sleep
在它之後放一個命令,否則在與它分離之前被cmd
, 的終止殺死。script.sh
cmd
我發現在後台正確執行的唯一方法是set -m
放入script.sh
. 為什麼在這種情況下有必要,而不是在第一種情況下?為什麼這兩種執行方式script.sh
(以及因此cmd
)之間的行為差異?我假設,在第一種情況下,監控模式沒有被啟動,正如你可以看到的
set -o
那樣script.sh
。
cmd
你應該執行的程序將被和SIGHUP
之間的信號殺死,任何包裝器或其他東西都沒有機會執行並產生任何影響。(您可以使用 進行檢查)fork()``exec()``nohup``strace
而不是
nohup
,您應該在執行後台命令之前在父 shell 中設置SIGHUP
為SIG_IGN
(ignore) ;如果信號處理程序設置為“忽略”或“預設”,則該處置將通過fork()
and繼承exec()
。例子:#! /bin/sh trap '' HUP # ignore SIGHUP xclock & trap - HUP # back to default
或者:
#! /bin/sh (trap '' HUP; xclock &)
如果您使用 執行此腳本
xfce4-terminal -H -x script.sh
,則後台命令 (xclock &
) 不會被SIGHUP
發送時script.sh
終止。當會話領導者(在您的情況下“擁有”控制終端的程序
script.sh
)終止時,核心將從其前台程序組SIGHUP
向所有程序發送一個;但是將啟用作業控制,並且以開頭的命令將被放入後台程序組中,並且不會由.set -m``&``SIGHUP
如果未啟用作業控制(非互動式腳本的預設設置),則以 開頭的命令
&
將在同一個前台程序組中執行,並且“後台”模式將通過重定向它們的輸入/dev/null
並讓它們忽略SIGINT
和來偽造SIGQUIT
。程序以這種方式從曾經作為前台作業執行但已經退出的腳本開始
SIGHUP
,因為它們的程序組(從其死去的父程序繼承)不再是終端上的前台。額外說明:
xterm
和xfce4-terminal
(可能還有其他基於 vte 的終端)之間的“保持模式”似乎不同。-e
雖然前者將保持 pty 的主端打開,但後者將在程序執行或退出後將其撕掉-x
,導致對從端的任何寫入都以EIO
. 當仍有來自前台程序組的程序在執行時,xterm
也會忽略消息(即它不會關閉)。WM_DELETE_WINDOW