Wie kann ich in zsh den Vordergrundprozess schneller ablehnen?

7

Meine Methode zum Ablehnen des Vordergrundprozesses erfordert zu viel Aufwand.

Angenommen, ich habe einen Prozess im zshVordergrund. Ich möchte disownes, damit ich die Shell schließen kann, ohne dass der Prozess gesendet wird SIGHUP.

Im Moment beginne ich mit Ctrl+ zzum Hintergrund und unterbreche dann den Vorgang

$ disown
disown: warning: job is suspended, use `kill -CONT -32240' to resume
$ kill -CONT -32240
$

- Dann kann ich das Terminal schließen.

Wie kann ich das automatisieren? Im Idealfall möchte ich in der Lage sein, Ctrl+ joder etwas zu drücken , um den laufenden Prozess sofort abzulehnen. Oder zweitbester, ich möchte in der Lage sein, einen einzelnen Befehl auszuführen, um sowohl SIGCONTden Prozess als auch den Prozess abzulehnen , sobald er angehalten ist.

Anko
quelle
4
Es ist einfacher, bg+ disownstatt kill -CONT -1234.
Jimmy
Ich habe alias dr='disown -r'in Bash verwendet. bgund drmach den Trick.
Peter Cordes

Antworten:

11

Eine globale Tastenkombination zum Deaktivieren des Vordergrundprozesses ist nicht möglich: Tastenanschläge werden vom Vordergrundprozess und nicht von der Shell empfangen. Sie müssen es zuerst mit Ctrl+ aussetzen, zwenn Sie es ablehnen möchten.

Es stellt sich jedoch heraus, dass es eine zsh-Option gibt, um das Ablehnen zu beschleunigen und dann fortzufahren : Mit setopt AUTO_CONTINUE, disownwird automatisch auch gesendetSIGCONT .

Sie können es also auf den Punkt bringen C-z disown.

Anko
quelle
11

Wenn Sie in einem Terminal Ctrl+ drücken Z, empfängt die Prozessgruppe im Vordergrund das Signal SIGTSTP (vorausgesetzt, das Terminal befindet sich im gekochten Modus und die Standardtastenbindungen sind vorhanden). Wenn der Prozess keinen Signalhandler für SIGTSTP festgelegt hat, wird der Prozess angehalten (und selbst wenn der Prozess einen Signalhandler festgelegt hat, führt er normalerweise nur eine geringe Menge an Verarbeitung durch, bevor er sich selbst anhält). Wenn ein Prozess beendet, angehalten oder fortgesetzt wird, wird sein übergeordnetes Element über ein SIGCHLD-Signal benachrichtigt. Aus diesem Grund zeigt die Shell eine neue Eingabeaufforderung und möglicherweise eine Meldung wie an [1] + 1234 suspended foo. Der Informationsfluss ist
    Schlüssel → Suspension → Shell
und nicht
    Schlüssel → Shell → Suspension,
sodass Sie für Ctrl+ keine andere Reaktion konfigurieren können Z.

Sie können einen Trap für SIGCHLD festlegen, der Trap wird jedoch nicht ausgeführt, wenn der Job der aktuelle Vordergrundjob ist. Zum größten Teil bedeutet dies, dass der Trap nur ausgeführt wird, wenn ein Hintergrundjob beendet wird, nicht wenn der Vordergrundjob beendet wird. Es bedeutet aber auch, dass Sie nicht auf die Unterbrechung des Vordergrundjobs reagieren können.

Sie können indirekt auf Änderungen in Hintergrundjobs reagieren, indem Sie einen precmdHook festlegen, der die Jobzustände mit den aus dem vorherigen precmdLauf gespeicherten Zuständen vergleicht . Aber ich weiß nicht, was Sie damit machen können: Es kann nur einen einzigen Suspend-Schlüssel geben, daher benötigen Sie einige zusätzliche Informationen, um zu wissen, ob der Prozess angehalten, im Hintergrund oder abgelehnt werden sollte.

Ich habe zsh so eingerichtet, dass das Drücken von Ctrl+ Zan einer leeren Eingabeaufforderung den aktuellen Job hinterlegt. Dadurch kann ich zweimal Ctrl+ drücken Z, um den Vordergrundjob mit nur einer kurzen Unterbrechung in den Hintergrund zu stellen.

fancy-ctrl-z () {
  if [[ $#BUFFER -eq 0 ]]; then
    bg
    zle redisplay
  else
    zle push-input
  fi
}
zle -N fancy-ctrl-z
bindkey '^Z' fancy-ctrl-z

Sie können es anrufen, disownwenn Sie möchten. Oder Sie können einen dritten Ctrl+ ZAnruf disownmit der folgenden ungetesteten Änderung veranlassen.

fancy-ctrl-z () {
  if [[ $#BUFFER -eq 0 ]]; then
    if (($fancy_ctrl_z_already_bg)); then
      disown
    else
      bg
      fancy_ctrl_z_already_bg=1
    fi
    zle redisplay
  else
    zle push-input
  fi
}
zle -N fancy-ctrl-z
bindkey '^Z' fancy-ctrl-z
fancy_ctrl_z_precmd () {
  fancy_ctrl_z_already_bg=0
}
precmd_functions+=fancy_ctrl_z_precmd
Gilles 'SO - hör auf böse zu sein'
quelle
Beachten Sie, dass Sie nicht den vollständig gekochten Modus benötigen, damit ^ Z funktioniert. isigist genug (auch ohne icanon)
Stéphane Chazelas
Also SIGTSTPwird das vom Terminalemulator gesendet? Ist es möglich, den Emulator (den Sie kennen) so zu konfigurieren, dass er seine Funktionsweise für einen ändert ^Z? Wie in der Verknüpfungspräferenz?
Franklin Yu
@FranklinYu Der Terminalemulator sendet SIGTSTP, wenn Sie Strg + Z drücken, während ein Programm ausgeführt wird und die Funktion in der Terminalschnittstelle ( stty +isig) aktiviert ist . Sie können mit dem Befehl stty ändern, welches Zeichen dies auslöst (Sie können keinen beliebigen Schlüssel festlegen, es muss ein einzelnes Byte sein, keine Escape-Sequenz). Während sich die Shell im Vordergrund befindet, werden die Terminaleinstellungen geändert, um das Drücken von Tasten zu übernehmen, sodass die Wirkung von Strg + Z von den Tastenbelegungen der Shell abhängt.
Gilles 'SO - hör auf böse zu sein'