web-dev-qa-db-ja.com

IGNOREEOFがZshで機能しないのはなぜですか?

Ctrl-Dを頻繁に使用してインタラクティブなpythonセッションを終了しますが、pythonセッションがオンになっていないときに、誤ってヒットすることがありました。これにより、 EOFシェルに移動し、続いてシェルを閉じます(確認を求めずに)。グーグルで2つの解決策を見つけました。

  1. set -o ignoreeof
  2. export IGNOREEOF=10

最初のオプションは、私のzshシェルとbashシェルで完全に機能しました。ただし、2番目のオプションはbashでのみ機能するようです。 zshを使用しているときは、IGNOREEOFに設定した数値に関係なく、設定されていないのと同じようにEOF)を送信します。

誰かがZSHがこのように動作する理由を手伝ってくれるでしょうか、それともzshシェルでの特殊なenv設定の結果でしょうか?

4
Zhenhua

Zshは、BashのようにIGNOREEOFパラメーターを使用しません。代わりに、setoptビルトインを介して設定する必要があるオプションです。 zshoptions(1)から:

IGNORE_EOF(-7)

ファイルの終わりで終了しないでください。代わりに、exitまたはlogoutの使用を要求します。 ただし、10回の連続したEOFにより、シェルはとにかく終了します。これにより、シェルのttyがなくなった場合にシェルがハングするのを防ぎます。

また、このオプションが設定され、Zshラインエディタが使用されている場合、シェル関数によって実装されたウィジェットは、通常の警告メッセージを出力せずにEOF(通常はControl-D))にバインドできます。これはのみ機能します。完了ウィジェットではなく、通常のウィジェット用。

-BashのIGNOREEOFをエミュレートする場合は、2番目の段落が重要です。下記参照

このオプションを有効にするには、シェル構成に以下を追加します。

setopt ignore_eof    # Option names are case-insensitive and underscores are optional.

Bashのエミュレート(オプション)

の数を指定できるというBashの動作をエミュレートしたい場合 Ctrl+D シェルを終了する前のシーケンスでは、次の ZLEウィジェット定義 *を構成に追加できます。

# Emulate Bash $IGNOREEOF behavior
bash-ctrl-d() {
  if [[ $CURSOR == 0 && -z $BUFFER ]]
  then
    [[ -z $IGNOREEOF || $IGNOREEOF == 0 ]] && exit
    if [[ $LASTWIDGET == bash-ctrl-d ]]
    then
      (( --__BASH_IGNORE_EOF <= 0 )) && exit
    else
      (( __BASH_IGNORE_EOF = IGNOREEOF-1 ))
    fi
    zle send-break
  else
    zle delete-char-or-list
  fi
}

次に、ウィジェットをZLEに追加し、そのためのキーバインドを作成します。

zle -N bash-ctrl-d
bindkey '^D' bash-ctrl-d

ただし、ignore_eofオプションを設定する必要があります。 Ctrl+D このウィジェットに関係なく、ZLEを無視し、すぐにシェルを終了します。回答の冒頭にあるマニュアルページスニペットの2番目の段落を参照してください。

*-このウィジェットの功績は、元の作者であるChristophLangeとBartSchaeferの訂正にあります。

5
ZeroKnight

私は見つけました:

   zle send-break

そして

    zle delete-char-or-list

lASTWIDGETは常にzle-line-initであり、bash-ctrl-dではないため、シェルは終了しません。 __BASH_IGNORE_EOFをデクリメントするには、これらの行を削除する必要がありました。のように:

# 2x ctrl-d to exit ...
export IGNOREEOF=1

# bash like ctrl-d wrapper for IGNOREEOF
setopt ignore_eof
function bash-ctrl-d() {
  if [[ $CURSOR == 0 && -z $BUFFER ]]
  then
    [[ -z $IGNOREEOF || $IGNOREEOF == 0 ]] && exit
    if [[ "$LASTWIDGET" == "bash-ctrl-d" ]]
    then
      (( --__BASH_IGNORE_EOF <= 0 )) && exit
    else
      (( __BASH_IGNORE_EOF = IGNOREEOF ))
    fi
  fi
}
zle -N bash-ctrl-d
bindkey "^d" bash-ctrl-d

私はzsh5.1.1を使用しています。 thx、-m

1
M Kelly