X11で始まり、グラフィカルで、自分のユーザーが殺せないプロセスを作成しようとしています。
具体的には、起動時に開始し、すぐにtmuxセッションを実行するurxvtドロップダウンターミナルがあります。私を悩ませているのは、私が時々それを殺すということです Alt+F4 ドロップダウン端末であることを忘れて、代わりに非表示にすることになっているとき。
確かに、別の端末からtmuxセッションに再接続できるため、tmuxセッションが失われることはありませんが、ドロップダウン端末を(正確な構成で)再起動して再接続する必要があり、面倒です。
私がやりたいのは、できないことです Alt+F4 この特定のプロセスを強制終了します。
これを読んだ後: Linuxでプロセスを強制終了できないようにする
私は、別のユーザーに属するものとしてプロセスを起動する必要があることを理解しましたが、自分のXサーバー内で次のようにしてそれを実行できたとしても。
Sudo xhost +local:
Sudo runuser -l my-secondary-user -c urxvt
私は2つの望ましくない行動に直面しています。
(2)は修正可能かもしれません-代わりにメインユーザーとしてログインするコマンドを実行するだけです-しかし、(1)を修正する方法がわかりません。
これを機能させる方法、または私がやりたいことを行う別の方法はありますか?可能であれば、カーネルモジュールの作成に煩わされることは避けたいと思います。
OpenboxでArchLinuxを実行する。
[〜#〜]編集[〜#〜]
この特定のウィンドウでAlt + F4を機能させないようにできるかもしれないと思いました。これが見つかりました: Openbox:アプリケーションごとにAlt-F4を無効にします
そして私のrc.xml
を次のように変更しました:
<keybind key="A-F4">
<action name="If">
<application class="URxvt"
title="tmux-session">
</application>
<then><!-- Do nothing for urxvt-tmux-session --></then>
<else>
<action name="Close" />
</else>
</action>
</keybind>
これは以前よりもわずかにうまく機能します:私はできません Alt+F4 その端末だけでなく、できません Alt+F4 現在、任意のurxvtウィンドウがあります(これは、新しいurxvtウィンドウがすべて同じクラス名で実行されているためだと思いますか?)
それに加えて、メニューバーから、または色合いパネルを右クリックして、あるいはもちろんコマンドによって、必要なものをすべて削除できます。しかし、このアプローチは次のことを意味します。
何か案は?
[〜#〜]ソリューション[〜#〜]
Dmitryの回答と上記の編集に基づいて、自分に合った解決策を見つけました。
1)カスタムタイトルをurxvtに設定しました:
urxvt -title urxvt-drop-down
カスタム名は使用しなかったのは、
urxvt -name urxvt-drop-down
コマンドは、現在使用している.Xresourcesファイルを無視しますが、-titleはそれを使用します。
2)私は Alt+F4 urxvt-drop-downというタイトルの端末を無視するためのkeybind。 rc.xml:
<keybind key="A-F4"> <action name="If"> <title>urxvt-drop-down</title> <then><!-- Do nothing for urxvt-drop-down --></then> <else> <action name="Close" /> </else> </action> </keybind>
3)犯人がタスクバーに表示されないようにしましたが、skip_taskbarもウィンドウのフォーカスを解除したため、再度フォーカスしました。 rc.xml:
<application title="urxvt-drop-down"> <skip_taskbar>yes</skip_taskbar> <focus>yes</focus> </application>
これで問題は解決しますが、基本的には回避策です。したがって、ステファンの答えがこの質問の正しい答えであるかどうかはまだわかりません。
何が行われているのかを理解するために、提示されたコマンドについて少し調査する必要があります。
偽の透明性とドロップダウン機能が必要なため、xtermは使用しません(xtermでも何らかのドロップダウンが可能かもしれませんが、透明性は確かにコンポジターなしではありません-そして私はそうします」 tコンポジターを使用)
xterm
に切り替えることがオプションである場合は、以下のハックを使用できます。ただし、いくつかの注意点があります。それらのほとんどに対処すると、ソリューションは非常に複雑になります。最後の最後のスクリプトを参照してください。
_xterm -e 'trap "" HUP; your-application'
_
ウィンドウマネージャーから閉じる命令を受け取ると、xterm
はSIGHUPをアプリケーションのプロセスグループに送信し、プロセスが戻ったときにのみ終了します。
これは、アプリケーションがSIGHUPのハンドラーをリセットせず、アプリケーションの子に望ましくない副作用をもたらす可能性があることを前提としています。
アプリケーションがtmux
の場合、どちらも問題のようです。
これらを回避するには、次のようにします。
_xterm -e sh -c 'bash -mc tmux <&1 & trap "" HUP; wait'
_
そうすれば、tmux
は別のプロセスグループで開始されるため、sh
のみがSIGHUPを受け取ります(無視します)。
さて、それはとにかくそれらのシグナルのハンドラーをリセットするtmux
には当てはまりませんが、一般的なケースでは、sh
の実装に応じて、SIGINT、SIGQUITシグナル、そして一般的に両方がbash
は非対話型のsh
から非同期コマンドとして開始されるため、アプリケーションでは無視してください。つまり、アプリケーションを中断することはできませんでした Ctrl+C または Ctrl+\。
これはPOSIXの要件です。 mksh
のようないくつかのシェルはそれを尊重しません(少なくとも現在のバージョンではありません)、またはSIGINTではそれを行うがSIGQUITではないdash
のような部分だけです。したがって、mksh
が利用可能な場合は、次のことができます。
_xterm -e mksh -c 'bash -mc your-application <&1 & trap "" HUP; wait'
_
(ただし、mksh
の将来のバージョンでは、その不適合を修正することを決定した場合、それは機能しない可能性があります)。
または、mksh
またはbash
が使用可能になることを保証できない場合、または将来変更される可能性のある動作に依存したくない場合は、Perl
たとえば、次のような_unclosable-xterm
_ラッパースクリプトを記述します。
_#! /bin/sh -
[ "$#" -gt 0 ] || set -- "${Shell:-/bin/sh}"
exec xterm -e Perl -MPOSIX -e '
$pid = fork;
if ($pid == 0) {
setpgrp or die "setpgrp: $!";
tcsetpgrp(0,getpid) or die "tcsetpgrp: $!";
exec @ARGV;
die "exec: $!";
}
die "fork: $!" if $pid < 0;
$SIG{HUP} = "IGNORE";
waitpid(-1,WUNTRACED)' "$@"
_
(_unclosable-xterm your-application and its args
_と呼ばれます)。
さて、もう1つの副作用は、作成してフォアグラウンドに配置している新しいプロセスグループ(上記の_bash -m
_またはsetpgrp
+ tcsetpgrp
)がセッションリーダープロセスグループではなくなったことです。 、したがって、もはや孤立したプロセスグループではありません(おそらく今それを気にかけている親がいます(sh
またはPerl
))。
それが意味するのは、押すと Ctrl+Z、そのプロセスは中断されます。ここでは、不注意な親が終了するだけです。つまり、プロセスグループはSIGHUPを取得します(そしてうまくいけば死にます)。
これを回避するには、子プロセスでSIGTSTPを無視することもできますが、アプリケーションがインタラクティブシェルの場合、mksh
、yash
、rc
などの実装では、 Ctrl-Z 彼らが実行するジョブに対しても機能しません。
または、次のように、停止するたびに子を再開する、より注意深い親を実装することもできます。
_#! /bin/sh -
[ "$#" -gt 0 ] || set -- "${Shell:-/bin/sh}"
exec xterm -e Perl -MPOSIX -e '
$pid = fork;
if ($pid == 0) {
setpgrp or die "setpgrp: $!";
tcsetpgrp(0,getpid) or die "tcsetpgrp: $!";
exec @ARGV;
die "exec: $!";
}
die "fork: $!" if $pid < 0;
$SIG{HUP} = "IGNORE";
while (waitpid(-1,WUNTRACED) > 0 && WIFSTOPPED(${^CHILD_ERROR_NATIVE})) {
kill "CONT", -$pid;
}' "$@"
_
もう1つの問題は、ウィンドウマネージャーからclose以外の理由でxterm
がなくなった場合、たとえばxterm
が強制終了されたり、Xサーバーへの接続が失われたりした場合です。 (xkill
、ウィンドウマネージャーのdestroyアクション、またはXサーバーのクラッシュなどのため)、これらの場合はSIGHUPも使用されるため、これらのプロセスは停止しません。それらを終了します。これを回避するには、端末デバイスでpoll()
を使用できます(xterm
が実行されると破棄されます)。
_#! /bin/sh -
[ "$#" -gt 0 ] || set -- "${Shell:-/bin/sh}"
exec xterm -e Perl -w -MPOSIX -MIO::Poll -e '
$pid = fork; # start the command in a child process
if ($pid == 0) {
setpgrp or die "setpgrp: $!"; # new process group
tcsetpgrp(0,getpid) or die "tcsetpgrp: $!"; # in foreground
exec @ARGV;
die "exec: $!";
}
die "fork: $!" if $pid < 0;
$SIG{HUP} = "IGNORE"; # ignore SIGHUP in the parent
$SIG{CHLD} = sub {
if (waitpid(-1,WUNTRACED) == $pid) {
if (WIFSTOPPED(${^CHILD_ERROR_NATIVE})) {
# resume the process when stopped
# we may want to do that only for SIGTSTP though
kill "CONT", -$pid;
} else {
# exit when the process dies
exit;
}
}
};
# watch for terminal hang-up
$p = IO::Poll->new;
$p->mask(STDIN, POLLERR);
while ($p->poll <= 0 || $p->events(STDIN) & POLLHUP == 0) {};
kill "HUP", -$pid;
' "$@"
_