交互式外壳能否变为非交互式,反之亦然?
注意:我已经对“交互式和非交互式之间的区别是什么?”这一基本问题进行了大量研究,研究的结果使我提出了这个问题。
这个问题的序言很长,部分原因是至关重要的是我们为回答“交互”所使用的定义类型。定义可以是特定集合的任意标签;它可以描述各种特性;或者它可以为您提供信息,以帮助您预测行为和了解目的。 我们可以将这最后一种称为“动作定义”或“动态定义”,这是最有用的。
在中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选项”和使用“操作数”一词开始,这是指Shell的调用,而不是可以在运行中的Shell中检查的属性。
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.
第一句话中的定义再次仅指壳的开始。
第二句(在我读)定义用作条件的代理建立外壳是否在被定义为使其成为特定的方式开始“互动”。
请注意,我不会将这句话解释为:“仅当$-
包含'i'时,bash shell才是交互式的。” $-
似乎只是一个方便的指示器,而不是交互式的定义。这与我的问题至关重要。
这两个(POSIX sh
定义和Bash的定义)都是机械定义,它们告诉标签“交互式”在什么情况下适用于您已启动的外壳。它们不是动作定义,因为它们没有给出此标签的任何含义。
但是,我看到在Bash手册页的其余部分中,都以某些方式对shell进行了混乱的引用,“除非是交互式shell,否则”或“仅在交互式shell中,或者设置了______选项”。(有很多示例,但这不是这个问题的重点。)
因此,我将接受“交互式”只是用于在手册页其余部分中描述的默认“交互式”行为(选项设置)集合的便捷标签。它本身不是基本术语或对象;它在外壳程序源代码之外没有权威定义。(例如,与术语“打开文件描述符”或“停止的进程”不同,后者指的是内核本身设计中内置的抽象。)
(尽管在的POSIX定义中也进行了定义sh
,但手册页[ man 1p sh
]的“除非外壳是交互式的”和类似的语句的用法要少得多man bash
,并且几乎专门针对调用时间的差异,因此,我将重点讨论Bash从现在开始。)
Shell处于“交互”状态的某些含义无论如何都仅在调用时相关,例如,外壳程序在读取其他命令之前已获取了哪些文件。但是,有是在任何时间相关的影响(至少在击)。因此,对于任何给定的运行中的 shell,必须有一种方法来判断它是否是交互式的。
set +i
在交互式Bash shell中运行会导致从的内容中删除“ 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重定向到它们不再连接到终端的位置,那么外壳是否会变得非交互式?
(似乎对此的回答是“否”,并且手册页可能包含修饰符:“其标准输入和错误都在调用时都连接到终端... ,但我不知道肯定地。)
如果回答是,“不,外壳不能成为非交互式的,反之亦然,”那么什么是明确的方法来确定是否shell是交互式?
换种说法:如果有“交互外壳”的行为在之后持续存在set +i
,该如何确定这些行为应继续适用?
为了避免有人怀疑它:有是一个shell的行为交互调用后坚持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
选项,我们可以看到交互式和非交互式shell之间的差异。以下脚本演示了这种差异的持久性:
#!/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}
带有未设置参数的类似测试会产生相似的结果,再次确认这$-
不是外壳交互性的“真相”。
那么,最后,外壳的确定的“交互性”特征存储在哪里?
而且,交互式外壳能否变为非交互式,反之亦然? (...通过更改此特征?)