私はX11から始めて、ユーザーが終了できないグラフィックプロセスを作成しようとしています。
具体的には、起動時に起動してすぐにtmuxセッションを実行するurxvtドロップダウン端末があります。私を迷惑にするのは、時々Altそれがドロップダウンターミナルであることを忘れて隠す必要があるときに+を使ってそれを殺すということです。F4
もちろん、他の端末から再接続できるため、tmuxセッションを失うことはありませんが、ドロップ端末を(正確な設定で)再起動して再接続する必要があります。
私がしたいことは この特定のプロセスをAlt終了できません。F4。
この記事を読んだ後: Linuxでプロセスを終了できないようにする
私は他のユーザーに属するプロセスを開始する必要があることを知っていますが、私のXサーバーでもこれを行うことができます。
sudo xhost +local:
sudo runuser -l my-secondary-user -c urxvt
私は2つの悪い行動に直面しています。
- マイメインユーザー(Xセッションを所有しているユーザー)がプロセスを終了できます。
- 仮想端末は(もちろん)my-secondary-userとしてログインを開始します。
(2)は変更可能です。コマンドを実行してデフォルトユーザーとしてログインします。しかし、(1)を修正する方法がわかりません。
これを行う方法はありますか、それとも私が望むものを実行する他の方法はありますか?可能であれば、カーネルモジュールの生成を避けたい。
Openboxを使用してArch Linuxを実行します。
編集する
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+することはできませんが、今はurxvtウィンドウも+できません。 (新しいurxvtウィンドウがすべて同じクラス名で実行されるためだと思いますか?)F4AltF4
さらに、メニューバーで色合いパネルを右クリックするか、コマンドを使用して必要な項目をすべて削除できます。ただし、このアプローチは次のことを意味します。
- Tint2パネルを右クリックしてドロップターミナルを終了できます。 (ドロップターミナルがパネルにアイコンで表示されないようにすると、問題が解決する可能性があります。研究によって可能になります。)
- Alt+他のターミナルウィンドウは利用できませんF4(あまり気に入らませんが、許可されるかもしれません)。
どんなアイデアがありますか?
答え1
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
SIGINT sh
、SIGQUIT信号は実装bash
に応じて非対話型信号として提供されるため、通常はアプリケーションでは無視されますsh
。あなたがあなたのアプリケーションを使用Ctrl+Cまたは中断するのを防ぎますCtrl+\。
これは POSIX 要件です。一部のシェルはmksh
これをサポートしていないか(少なくとも現在のバージョンではない)、dash
SIGINTを部分的にのみサポートし、SIGQUITはサポートしません。したがって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;
}' "$@"
xterm
もう一つの質問は、他の理由で消えた場合です。閉鎖たとえば、xterm
Xサーバーへの接続が終了または切断された場合(例xkill
:破壊するたとえば、ウィンドウマネージャのタスクまたは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;
' "$@"
答え2
あなたの質問には、研究を間違った方向に導くという誤解を招くタイトルがあります。窓を閉めるとX
、サーバーはプロセスを終了しません。代わりにWM_DELETE_WINDOW
プロセスにメッセージを送信し、プロセスは終了します。この事実は最初のアプローチを台無しにします。フラグを設定しても引き続きSIGNAL_UNKILLABLE
オフにできます。
2番目の方法は効果があるようです。単一の端末ウィンドウと他のすべてのウィンドウを区別するだけです。これを達成する1つの方法は、urxvt
特定のタイトル(たとえば)で始まり、urxvt -name urxvt-iddqd
その名前のルールを作成することです。
<keybind key="A-F4">
<action name="If">
<application title="urxvt-iddqd"
title="tmux-session">
</application>
<then><!-- Do nothing for urxvt-tmux-session --></then>
<else>
<action name="Close" />
</else>
</action>
</keybind>
答え3
質問作成者は次の解決策を提示します。
私に合った解決策を見つけました。ドミトリーの答え上記の編集内容は次のとおりです。
- 私のカスタムタイトルを設定しました
urxvt
。urxvt -title urxvt-drop-down
次のようなので、カスタム名を使用しませんでした。
urxvt -name urxvt-drop-down
.Xresources
このコマンドは、現在使用中のファイルを無視して-title
代わりに使用します。
- Alt+キーバインディングを使用してタイトル付きのF4端末を無視します
urxvt-drop-down
。 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>
- 犯人がタスクバーに表示されないようにし、ウィンドウの
skip_taskbar
フォーカスもぼやけているため、再びフォーカスを合わせました。rc.xml
:<application title="urxvt-drop-down"> <skip_taskbar>yes</skip_taskbar> <focus>yes</focus> </application>
これは問題を解決しましたが、本質的に解決策です。だからまだわかりませんが、スティーブンの答えこれは質問に対する正解です。
実行している作業を理解するには、提供されたコマンドに関するいくつかの研究が必要です。
しかし、私はそれを使用しません
xterm
。なぜなら、私は偽の透明度とドロップダウン機能が欲しいからです(私の考えはxtermにもある種のドロップダウン機能があるかもしれないと思いますが、透明度はコンポジターなしでは確かに不可能です。そしてコンポジターを使用しません)。