対話型シェルは非対話型になりますか?


15

対話型シェルは非対話型になりますか?

注:「対話型と非対話型の違いは何ですか?」という基本的な質問について多くの研究を行ってきましたが、研究の結果、この質問をすることになりました。

この質問には、回答するために「インタラクティブ」にどのタイプの定義を使用するかが重要であるため、部分的に長い前文があります。定義は、特定のセットの任意のラベルです。さまざまなプロパティを説明できます。または、行動予測し目的を理解するために使用できる情報を提供できます この最後のタイプは、「アクション定義」または「動的定義」と呼ぶことができ、最も便利です。


ではman 1p sh、対話型シェルの次の定義が提供されています。

   If the -i option is present, or  if  there  are  no  operands  and  the
   shells  standard  input and standard error are attached to a terminal,
   the shell is considered to be interactive.

「-iオプション」の記述と「オペランド」という言葉の使用から、これは実行中のシェルで調べることができる属性ではなく、シェルの呼び出しを指します。

Bashのマニュアルページでは、少し異なる表現をしています。

   An interactive shell is one started without  non-option  arguments  and
   without the -c option whose standard input and error are both connected
   to terminals (as determined by isatty(3)), or one started with  the  -i
   option.   PS1 is set and $- includes i if bash is interactive, allowing
   a shell script or a startup file to test this state.

最初の文の定義は、シェルの開始のみを参照しています。

2番目の文(私の読書では)は、「対話型」として定義されている特定の方法でシェルが開始されたかどうかを確立するためのプロキシとして使用される条件を定義します

この文は、「 'i'が含まれている場合にのみ、bashシェルはインタラクティブです」と解釈ていない$- こと注意してください$-単なる便利なインジケータであり、インタラクティブの定義ではないようです。これは私の質問に非常に重要です。


これらの両方(POSIX sh定義とBashの定義)は、起動したシェルに「対話型」というラベルがどのような状況で適用されるかを示す機械的な定義です。これらはこのラベルの意味を与えないので、アクションの定義ではありません。

ただし、Bashのマニュアルページの残りの部分では、「対話型シェルでない限り」または「対話型シェルでのみ、または_____オプションが設定されている場合」特定の方法で動作するシェルへの参照が散在しています。(多数の例がありますが、それがこの質問の要点ではありません。)

したがって、「対話型」は、残りのマニュアルページ全体で説明されているデフォルトの「対話型」動作(オプション設定)のコレクションの単なる便利なラベルであることを受け入れます。それ自体は基本的な用語やオブジェクトではありません。シェルのソースコード以外には信頼できる定義はありません。(たとえば、カーネル自体の設計に組み込まれた抽象化を指す「ファイル記述子を開く」または「プロセスを停止」という用語とは異なります。)

(POSIXの定義でも定義されていますがsh、manページ[ man 1p sh]は「シェルが対話的でない限り」および類似のステートメントの使用がはるかに少なくman bash、呼び出し時間の違いにほぼ専念しているため、Bashに焦点を当てますこの時点以降。)


シェルが「対話式」であるという意味のいくつかは、いずれにせよ、起動時にのみ関連します。たとえば、シェルが他のコマンドを読み取る前にどのファイルをソースとするかなどです。ただし、(少なくともBashでは)いつでも関連する影響があります。したがって、任意の実行中のシェルに対して、対話型かどうかを判断する方法が必要です。

set +i対話型のBashシェルで実行すると、のコンテンツから「i」が削除され$-ます。

問題は、これは実際にシェルがもはや対話的ではなくなったことを意味しますか?

Bashの正確な定義では、定義のどこにも「i」が存在する必要ないため、そうすべきはありません$-

   An interactive shell is one started without  non-option  arguments  and
   without the -c option whose standard input and error are both connected
   to terminals (as determined by isatty(3)), or one started with  the  -i
   option.

厳密な定義を厳密に読み取ると、疑問が生じます。対話型端末のstdinまたはstderrがリダイレクトされ、端末に接続されなくなった場合、シェルは非対話型になりますか?

表示され、「その標準入力と標準エラーの両方...端子に接続されています。この1への答えが「NO」とmanページが修飾含まれていない可能性があることを、呼び出し時に」私は知りません間違いなく。)


答えが「いいえ、シェルが非対話型にならない、またはその逆はできない」場合、シェルが対話型かどうかを決定する決定的な方法は何ですか?

さらに別の言い方をすると、「対話型シェル」の動作が後set +iに持続する場合、それらの動作が引き続き適用されるべきであると判断するために何が使用されますか?


ないように誰もがそれを疑う:ありますシェルの振る舞いは後も持続され、対話的に呼び出さset +iとシェルの行動が後も持続た非対話的に呼び出されますset -i。例として、次の抜粋を検討してman bashください。

COMMENTS
   In a non-interactive shell, or an interactive shell in which the inter-
   active_comments  option  to  the  shopt  builtin  is enabled (see SHELL
   BUILTIN COMMANDS below), a word beginning with # causes that  word  and
   all  remaining  characters  on that line to be ignored.  An interactive
   shell without the interactive_comments option enabled  does  not  allow
   comments.  The interactive_comments option is on by default in interac-
   tive shells.

したがって、interactive_commentsオプションの設定を解除すると、インタラクティブシェルと非インタラクティブシェルの違いがわかります。この違いの持続性は、次のスクリプトによって示されます。

#!/bin/bash

# When the testfile is run interactively,
# all three comments will produce an error
# (even the third where 'i' is not in '$-').
# When run noninteractively, NO comment will
# produce an error, though the second comment
# is run while 'i' IS in '$-'.

cat >testfile <<'EOF'
shopt interactive_comments
shopt -u interactive_comments
shopt interactive_comments
echo $-
#first test comment
set -i
echo $-
#second test comment
set +i
echo $-
#third test comment
EOF

echo 'running bash -i <testfile'
bash -i <testfile
echo 'running bash <testfile'
bash <testfile

これにより、「対話型」と「iの値にある$-」は同等ではないことが確認されます。

${parameter:?word}パラメータを設定せずに使用した同様のテストでは、同様の結果が得られ、$-シェルの対話性の「真実の源」ではないことが確認されました。


それで、最後に、シェルの決定的な「対話性」特性はどこに保存されていますか?

また、インタラクティブシェルが非インタラクティブになったり、その逆になることはありますか? (...この特性を変更することにより?)


回答:


9

私が尋ねる質問は、誰がそれをしたいのでしょうか?

次のような対話型シェルのいくつかの側面を無効にできます。

  • PS1= PS2= プロンプトを無効にする
  • set +m ジョブ制御を無効にする
  • 一部のシェルで履歴を無効にする
  • zleですべての完了モジュールをアンロードできる場合がありますzsh

しかし、シェルが対話的であるのを止めたい場合は、代わりに以下を行うことができます

. /some/file; exit

コマンドの残りの部分を得るためにそれを伝えるために/some/file(と交換し/dev/tty、まだの行動のような非対話型シェルからいくつかの相違点、があるだろうが、それでもコマンドがttyデバイスから読み取ることがしたい場合)、returnまたは事実それでもジョブ制御を行うこと、または:

exec myshell /dev/tty

現在の対話型シェルを、ttyデバイスからコマンドを読み取る非対話型シェルに置き換えるため。

bash 4.4では、他のほとんどのシェルと同様にset +iaを返すことに注意してくださいbash: set: +i: invalid option


それがやるのはばかげたことになると絶対に同意した。 私が述べた「インタラクティブ」の概念は、シェルと対話するときに役立つデフォルトの動作のコレクションにすぎないということです。これらの動作のそれぞれを個別に変更でき、各動作を変更する場合、「まだ対話型のシェルですか?」という質問があります。とんでもないセマンティクスです。それは重要な質問すらありません。 ただし
ワイルドカード

1
@Wildcard、exec < <(sleep infinity)インタラクティブシェルで行う場合、あまりインタラクティブではないインタラクティブシェルがあります。シェルは、それ自体がインタラクティブである$-と見なしますが、それはまだ含まれてiいますが、そうではないかもしれません。それについて議論することがもっとあるかどうかはわかりません。
ステファンシャゼル

2
@Wildcard、シェルがとして起動されたinteractive場合、そのままです。set +i古いbashバージョンでできることはバグでした。
ステファンシャゼラス

1
@Wildcard、のソースコードを見ると、bashおそらくinteractiveiフラグにマップされるグローバルブール変数があることがわかります$-。このブール値を変更しても、対話型シェルのすべての動作が自動的に変更されるわけではありません。対話型から非対話型への変更はサポートされていません。
ステファンシャゼラス

4
@Wildcard Dashはset +iプロンプトを受け入れ、表示を停止します。これはユーザーが行うべきものではないため、動作がシェルに依存し、シェル実装者による意図的な決定の結果ではなく偶発的なことが多いことは驚くことではありません。
ジル 'SO-悪であるのをやめる'
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.