端末コマンド以外の方法で閉じないXウィンドウを作成する方法

端末コマンド以外の方法で閉じないXウィンドウを作成する方法

私はX11から始めて、ユーザーが終了できないグラフィックプロセスを作成しようとしています。

具体的には、起動時に起動してすぐにtmuxセッションを実行するurxvtドロップダウン端末があります。私を迷惑にするのは、時々Altそれがドロップダウンターミナルであることを忘れて隠す必要があるときに+を使ってそれを殺すということです。F4

もちろん、他の端末から再接続できるため、tmuxセッションを失うことはありませんが、ドロップ端末を(正確な設定で)再起動して再接続する必要があります。

私がしたいことは この特定のプロセスをAlt終了できません。F4

この記事を読んだ後: Linuxでプロセスを終了できないようにする

私は他のユーザーに属するプロセスを開始する必要があることを知っていますが、私のXサーバーでもこれを行うことができます。

    sudo xhost +local:
    sudo runuser -l my-secondary-user -c urxvt

私は2つの悪い行動に直面しています。

  1. マイメインユーザー(Xセッションを所有しているユーザー)がプロセスを終了できます。
  2. 仮想端末は(もちろん)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

さらに、メニューバーで色合いパネルを右クリックするか、コマンドを使用して必要な項目をすべて削除できます。ただし、このアプローチは次のことを意味します。

  1. Tint2パネルを右クリックしてドロップターミナルを終了できます。 (ドロップターミナルがパネルにアイコンで表示されないようにすると、問題が解決する可能性があります。研究によって可能になります。)
  2. Alt+他のターミナルウィンドウは利用できませんF4(あまり気に入らませんが、許可されるかもしれません)。

どんなアイデアがありますか?

ベストアンサー1

xterm切り替えるオプションがある場合は、以下のトリックを使用できます。ただし、いくつかの注意事項があります。これらのほとんどが解決されると、ソリューションはかなり複雑になります。最後の最後のスクリプトを参照してください。

xterm -e 'trap "" HUP; your-application'

ウィンドウマネージャから終了コマンドを受信すると、xtermSIGHUPはアプリケーションのプロセスグループに送信され、プロセスが返されたときにのみ終了します。

アプリケーションがSIGHUPハンドラをリセットせず、アプリケーションのサブアプリケーションに望ましくない副作用がある可能性があるとします。

あなたのアプリケーションがtmux

これらの問題を解決するには、次のようにします。

xterm -e sh -c 'bash -mc tmux <&1 & trap "" HUP; wait'

これはtmux他のプロセスグループから開始されるため、shSIGHUPのみを受信して​​無視します。

これはこれらの信号のハンドラをリセットするのには適用されませんが、通常、tmuxSIGINT sh、SIGQUIT信号は実装bashに応じて非対話型信号として提供されるため、通常はアプリケーションでは無視されますsh。あなたがあなたのアプリケーションを使用Ctrl+Cまたは中断するのを防ぎますCtrl+\

これは POSIX 要件です。一部のシェルはmkshこれをサポートしていないか(少なくとも現在のバージョンではない)、dashSIGINTを部分的にのみサポートし、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を無視することができますが、アプリケーションがインタラクティブシェルの場合、一部の実装(またはmkshyashrc場合は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もう一つの質問は、他の理由で消えた場合です。閉鎖たとえば、xtermXサーバーへの接続が終了または切断された場合(例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;
  ' "$@"

おすすめ記事