Как создать окно X, которое не будет закрыто каким-либо образом, кроме команды терминала

Я пытаюсь создать процесс, который начнется с X11, будет графическим и unkilable моим собственным пользователем.

Более конкретно, у меня есть раскрывающийся список urxvt, начинающийся с момента запуска и запускающий сеанс tmux сразу. Меня раздражает то, что я иногда убиваю его с помощью Alt + F4, когда забываю, что это выпадающий терминал, и я должен скрыть его.

Конечно, я не теряю сеанс tmux, так как я могу подключиться к нему с другого терминала, но мне придется перезапустить выпадающий терминал (с точной конфигурацией) и снова подключиться, и это утомительно.

То, что я хотел бы сделать, заключается в том, чтобы не позволить Alt + F4 убить этот конкретный процесс .

После прочтения этого: Сделайте процесс unkillable в Linux

Я понял, что должен запустить процесс как принадлежащий другому пользователю, но даже если мне удастся сделать это на моем собственном сервере X, с помощью:

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

Я сталкиваюсь с двумя нежелательными поведением:

  1. Этот процесс можно убить моим главным пользователем (тем, кто владеет X-сессией)
  2. Виртуальный терминал начинает регистрироваться как мой вторичный пользователь (конечно)

(2) может быть спрямляемым – просто запустите команду для входа в систему как мой основной пользователь, но я не знаю, как исправить (1).

Есть ли способ сделать эту работу или другим способом сделать то, что я хочу? Я бы предпочел не связываться с созданием модулей ядра, если это возможно.

Запуск Arch Linux с Openbox.

РЕДАКТИРОВАТЬ

Я подумал, что я могу заставить 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 работают под одним и тем же именем класса?)

Кроме того, я могу убить все, что мне нужно, в строке меню или щелкнуть правой кнопкой мыши на панели оттенков или, конечно же, по команде. Но этот подход означает, что:

  1. Я все еще могу убить свой выпадающий терминал, щелкнув правой кнопкой мыши на панели tint2 (возможно, исправляемый, если я создаю выпадающий терминал, не отображающийся как значок на панели), должен быть возможен с некоторыми исследованиями)
  2. Я не могу использовать другие окна терминала Alt + F4 (не нравится это много, но, возможно, приемлемо)

Есть идеи?

РЕШЕНИЕ

Я нашел решение, которое работает для меня на основе ответа Дмитрия и моего вышеизложенного:

1) Я установил пользовательский заголовок для моего urxvt:

urxvt -title urxvt-drop-down

Я не использовал пользовательское имя, потому что кажется, что

urxvt -name urxvt-drop-down

команда игнорирует файл .Xresources, который я использую сейчас, в то время как -title использует его.

2) я заставил клавиатуру 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>

3) Я заставил преступника никогда не появляться на панели задач, и поскольку skip_taskbar также не сфокусирует окно, переориентируйте его. rc.xml:

<application title="urxvt-drop-down"> <skip_taskbar>yes</skip_taskbar> <focus>yes</focus> </application>

Хотя это решает проблему для меня, это, по сути, обходной путь. Таким образом, я еще не уверен, что ответ Стефана правильный для этого вопроса.

Необходимо сделать небольшое исследование команд, представленных для понимания того, что делается.

Я не буду использовать xterm, хотя, поскольку я хочу фальшивую прозрачность и возможность выпадающего списка (возможно, что-то вроде выпадающего списка с xterm, но я уверен, что прозрачность, конечно, не без композитора, и я выиграл ' t используйте композитор)

2 Solutions collect form web for “Как создать окно X, которое не будет закрыто каким-либо образом, кроме команды терминала”

Если переключение на 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 , не 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 ).

Теперь другой побочный эффект заключается в том, что новая группа процессов, которую мы создаем и setpgrp на передний план (с bash -m или setpgrp + tcsetpgrp выше) больше не является группой процессов лидера сеанса, поэтому больше не является осиной группой процессов (есть родительская группа предположительно ухаживая за ним сейчас ( sh или perl )).

Это означает, что при нажатии Ctrl + Z этот процесс будет приостановлен. Здесь наш неосторожный родитель просто выйдет, а это значит, что группа процессов получит SIGHUP (и, надеюсь, умрет).

Чтобы избежать этого, мы могли бы просто игнорировать SIGTSTP в дочернем процессе, но тогда, если ваше приложение является интерактивной оболочкой, для некоторых реализаций, таких как mksh , mksh или 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; ' "$@" 

Ваш вопрос имеет несколько вводящий в заблуждение заголовок, ведущий ваши исследования в неправильном направлении. Когда вы закрываете окно в X , сервер не убивает ваш процесс . Вместо этого он отправляет в WM_DELETE_WINDOW сообщение WM_DELETE_WINDOW , которое, в свою очередь, завершается. Этот факт обрекает ваш первый подход: даже если вы установите флаг SIGNAL_UNKILLABLE , вы все равно сможете его закрыть.

Ваш второй подход кажется удобным, все, что вам нужно сделать, – это отличить одно окно терминала от всех остальных. Один из способов добиться этого – запустить 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> 
  • Как получить список ключей, загруженных в настоящее время с помощью XKB?
  • Ищете карту xinit / startx rabbithole
  • Запись видео и аудио с приложения X-Window
  • Захват трафика протокола X11
  • xautolock / ssh-add не может взаимодействовать с ssh-agent при запуске из .xsessionrc
  • Как ключи или ключевые коды сопоставляются с символами X Key?
  • X11 - несколько мониторов, видимых как один монитор
  • Добавить выход VIRTUAL в Xorg
  • Отключение звука от конкретного виртуального дисплея
  • Удалить форматирование из буфера копирования / вставки
  • Как подключиться к X-приложению через VNC, который был запущен xvfb-run?
  • Linux и Unix - лучшая ОС в мире.