J'essaie de créer un process qui commencera avec X11, sera graphique et inutilisable par mon propre user.
Plus précisément, j'ai un terminal déroulant urxvt commençant au démarrage et exécutant une session tmux tout de suite. Ce qui m'énerve, c'est que je le tue parfois avec Alt + F4 quand j'oublie que c'est le terminal déroulant et je suis censé le cacher à la place.
Bien sûr, je ne perds pas ma session tmux puisque je peux la rattacher à un autre terminal, mais je devrai relancer le terminal déroulant (avec la configuration exacte) et le rattacher et c'est fastidieux.
Ce que je voudrais faire, c'est de ne pas être en mesure d' Alt + F4 tuer ce process spécifique .
Après avoir lu ceci: rendre un process inexploitable sur Linux
J'ai compris que je devrais lancer le process comme appartenant à un autre user, mais même si je réussis à le faire dans mon propre server X avec:
sudo xhost +local: sudo runuser -l my-secondary-user -c urxvt
Je fais face à deux comportements indésirables:
Le (2) peut être rectifiable – il suffit d'exécuter une command pour se connecter en tant que mon user principal à la place – mais je n'ai aucune idée sur la façon de réparer le (1).
Y a-t-il moyen de faire ce travail, ou une autre façon de faire ce que je veux? Je préfère éviter d'avoir à créer des modules du kernel si possible.
Exécuter Arch Linux avec Openbox.
MODIFIER
J'ai pensé que je pourrais faire en sorte que Alt + F4 ne fonctionne pas pour cette window spécifique. trouvé ceci: Openbox: désactiver Alt-F4 sur une base d'application
et modifié mon rc.xml
ainsi:
<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>
Cela fonctionne un peu mieux qu'avant: je ne peux pas Alt + F4 ce terminal, mais je ne peux pas non plus Alt + F4 n'importe quelle window urxvt maintenant (devinez parce que les nouvelles windows urxvt sont toutes exécutées sous le même nom de class?)
En plus de cela, je peux tuer tout ce dont j'ai besoin dans la barre de menu, ou bien cliquer avec le button droit de la souris sur mon panneau de teinte, ou, bien sûr, par command. Mais cette approche signifie que:
Des idées?
SOLUTION
J'ai trouvé une solution qui fonctionne pour moi en me basant sur la réponse de Dmitry et mes modifications ci-dessus:
1) je fixe un titre personnalisé à mon urxvt:
urxvt -title urxvt-drop-down
Je n'ai pas utilisé un nom personnalisé parce qu'il semble que le
urxvt -name urxvt-drop-down
command ignore le file .Xresources que j'utilise actuellement, tandis que -title l'utilise.
2) J'ai fait la touche Alt + F4 pour ignorer les terminaux intitulés 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) J'ai fait que le coupable n'apparaisse jamais dans la barre des tâches, et puisque la barre skip_taskbar décompose également la window, la recentre. rc.xml:
<application title="urxvt-drop-down"> <skip_taskbar>yes</skip_taskbar> <focus>yes</focus> </application>
Même si cela résout le problème pour moi, c'est essentiellement une solution de contournement. Je ne suis donc pas encore sûr que la réponse de Stéphane soit la bonne pour cette question.
Besoin de faire un peu de search sur les commands présentées pour comprendre ce qui se fait.
Je n'utiliserai cependant pas xterm, car je veux une transparence et une capacité de drop-down (une sorte de drop-down pourrait être possible avec xterm aussi je pense, mais la transparence n'est certainement pas sans un compositeur – et j'ai gagné ' t utiliser un compositeur)
Si le passage à xterm
est une option, vous pouvez utiliser le hack ci-dessous. Il y a cependant quelques mises en garde. Une fois que vous répondez à la plupart d'entre eux, la solution finit par se compliquer, voir le script final à la fin.
xterm -e 'trap "" HUP; your-application'
A la réception de l'instruction de fermeture du gestionnaire de windows, xterm
enverra un SIGHUP au groupe de process de votre application et ne se quittera que lorsque le process sera rétabli.
Cela suppose que votre application ne réinitialise pas le gestionnaire pour SIGHUP et pourrait avoir des effets secondaires indésirables pour les enfants de votre application.
Les deux semblent être un problème si votre application est tmux
.
Pour contourner ceux-ci, vous pourriez faire:
xterm -e sh -c 'bash -mc tmux <&1 & trap "" HUP; wait'
De cette façon, tmux
serait lancé dans un groupe de process différent, de sorte que seul le sh
recevrait le SIGHUP (et l'ignorer).
Cela ne s'applique pas à tmux
qui réinitialise le gestionnaire pour ces signaux, mais dans le cas général, en fonction de votre implémentation de sh
, les signaux SIGINT, SIGQUIT et généralement les deux seront ignorés pour votre application car ce bash
est démarré comme une command asynchronous à partir d'un sh
non-interactif. Cela signifie que vous ne pouvez pas interrompre votre application avec Ctrl + C ou Ctrl + \ .
C'est une exigence POSIX. Certains shells comme mksh
ne l'honorent pas (du less pas les versions actuelles), ou seulement en partie comme dash
qui le fait pour SIGINT mais pas SIGQUIT. Donc, si mksh
est disponible, vous pourriez faire:
xterm -e mksh -c 'bash -mc your-application <&1 & trap "" HUP; wait'
(bien que cela puisse ne pas fonctionner dans les futures versions de mksh
s'ils décident de corriger cette non-conformité).
Ou si vous ne pouvez pas garantir que mksh
ou bash
sera disponible ou préférez ne pas countr sur un comportement qui pourrait changer à l'avenir, vous pouvez faire leur travail à la main avec perl
et par exemple écrire un script wrapper unclosable-xterm
comme:
#! /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)' "$@"
(pour être appelé unclosable-xterm your-application and its args
).
Un autre effet secondaire est que ce nouveau groupe de process que nous créons et mettons en avant-plan (avec bash -m
ou setpgrp
+ tcsetpgrp
ci-dessus) n'est plus le groupe de process leader de session, donc plus un groupe de process orphelins soi-disant soigné maintenant ( sh
ou perl
)).
Cela signifie que lorsque vous appuyez sur Ctrl + Z , ce process sera suspendu. Ici, notre parent insouciant va juste quitter, ce qui signifie que le groupe de process obtiendra un SIGHUP (et j'espère mourir).
Pour éviter cela, nous pourrions simplement ignorer le SIGTSTP dans le process enfant, mais si votre application est un shell interactif, Ctrl-Z ne fonctionnera pas pour les tâches exécutées pour certaines implémentations comme mksh
, yash
ou rc
.
Ou nous pourrions mettre en place un parent plus prudent qui reprend l'enfant chaque fois qu'il est arrêté, comme:
#! /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; }' "$@"
Un autre problème est que si xterm
disparu pour une autre raison que la fermeture du gestionnaire de windows, par exemple si xterm
est tué ou perd la connection au server X (à cause de xkill
, l'action de destruction de votre gestionnaire de windows ou du server X crashes par exemple), alors ces process ne mourront pas car SIGHUP serait également utilisé dans ces cas pour les terminer. Pour contourner cela, vous pouvez utiliser poll()
sur le terminal (qui serait démoli quand xterm
va):
#! /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; ' "$@"
Votre question a un titre quelque peu trompeur, menant votre search dans la mauvaise direction. Lorsque vous fermez une window dans X
, le server ne tue pas votre process . Au lieu de cela, il envoie un message WM_DELETE_WINDOW
au process, qui à son tour se termine. Ce fait condamne votre première approche: même si vous définissez le drapeau SIGNAL_UNKILLABLE
, vous pourrez toujours le fermer.
Votre deuxième approche semble utilisable, tout ce que vous avez à faire est de discriminer une window de terminal unique contre tous les autres. Une façon d'y parvenir est de lancer urxvt
avec un titre particulier, par exemple urxvt -name urxvt-iddqd
, et créer une règle pour son nom:
<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>