web-dev-qa-db-ja.com

インタラクティブシェルを非インタラクティブにすることはできますか?

インタラクティブシェルを非インタラクティブにすることはできますか?

注:「インタラクティブと非インタラクティブの違いは何ですか?」という基本的な質問について多くの調査を行いましたが、私の調査結果からthis質問します。

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


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

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

「-iオプション」の言及とWordの「オペランド」の使用から、これはシェルのinvocation、を指し、実行中のシェルで検査できる属性ではありません。

Bashのmanページでは、少し異なる表現をしています。

   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.

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

2番目の文(私のリーディング)では、シェルを「インタラクティブ」にするように定義された特定の方法で開始されたかどうかを確立するために、プロキシとして使用される条件を定義しています。

I do notはこの文を次のように解釈することに注意してください:「$-に 'i'が含まれている場合にのみ、bashシェルはインタラクティブです。」$-definitionインタラクティブではなく、単なる便利なインジケータのようです。これは私の質問に決定的に関連しています。


これらの両方(POSIX sh定義とBashの定義)は、開始したシェルに「インタラクティブ」というラベルがどのような状況で適用されるかを伝える機械的な定義です。これらはアクションの定義ではなく、このラベルの含意を示していません。

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

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

(これはshのPOSIX定義でも定義されていますが、そのマニュアルページ[man 1p sh]は、「シェルがインタラクティブでない限り」やman bashと同様のステートメントの使用がはるかに少なく、ほぼすべてが呼び出し時間の違いに焦点を当てているため、ここからはBashに焦点を当てます。)


シェルが「対話型」であることの影響の一部は、とにかく関係がある呼び出し時とにかく、他のコマンドを読み取る前にシェルがどのファイルをソースとしているかなど。ただし、いつでも関連するareの影響(少なくともBashでは)があります。したがって、任意のrunning Shellについて、インタラクティブかどうかを伝える方法が必要です。

インタラクティブBashシェルでset +iを実行すると、$-のコンテンツから「i」が削除されます。

質問は:これは実際にシェルがインタラクティブではなくなったことを意味しますか?

Bashの正確な定義によれば、それはshould n't、定義のどこにもないためrequired '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がリダイレクトされて、端末に接続されなくなった場合、シェルは非対話型になりますか?

(それはappearsこれに対する答えは "no"であり、manページには修飾子を含めることができます: "標準入力とエラーの両方が端末に接続されています...at呼び出しの時間、 "しかし、私は決定的に知りません。)


答えが「いいえ、シェルが非インタラクティブになることはできず、その逆も同様です」である場合、シェルがインタラクティブであるかどうかを判断するdefinitive方法は何ですか?

さらに別の言い方をすると:set +iの後も持続する「インタラクティブシェル」の動作がある場合、何が使用されるかこれらの動作を引き続き適用する必要があると判断する?


誰もそれを疑わないでください:areset +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がある」がnotと同等であることを確認します。

${parameter:?word}を未設定のパラメーターと共に使用して同様のテストを行うと、同様の結果が得られ、$-がシェルの対話性の「信頼できる情報源」ではないことを確認します。


それで、最後に、シェルの決定的な「インタラクティブ性」特性はどこに保存されていますか?

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

17
Wildcard

私が尋ねる質問はなぜ誰もがそれをしたいのですか?です。

次のようなインタラクティブシェルの一部の機能を無効にすることができます。

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

ただし、シェルの対話性を停止したい場合は、代わりに次のようにすることができます。

. /some/file; exit

残りのコマンドを/some/fileから取得するように指示するには(コマンドをttyデバイスから読み取りたい場合は/dev/ttyで置き換えてください)、非対話式とは多少の違いがありますreturnの動作や、それでもジョブ制御を実行するという事実や次のようなシェル。

exec myshell /dev/tty

現在のインタラクティブシェルを、ttyデバイスからコマンドを読み取る非インタラクティブシェルに置き換えるには.

Bash 4.4では、他のほとんどのシェルと同様に、set +ibash: set: +i: invalid optionを返します。

9