交互式 shell 可以变成非交互式 shell,反之亦然吗?
笔记:我对这个基本问题做了很多研究,“交互式和非交互式有什么区别?”,我的研究结果让我问这问题。
这个问题有一个很长的序言,部分原因是它至关重要类型为了回答这个问题,我们使用“交互”的定义。定义可以是某个集合的任意标签;它可以描述各种属性;或者它可以为您提供可用于预测行为并理解目的。 最后一种类型我们可以称之为“动作定义”或“动态定义”,它是最有用的。
在 中man 1p sh
,给出了交互式 shell 的以下定义:
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.
第一句中的定义再次仅指开始一个贝壳的。
第二句话(在我的阅读中)定义了用作的条件代理确定 shell 是否以定义为“交互”的特定方式启动。
注意我愿意不是将这句话解释为:“当且仅当$-
包含‘i’时,bash shell 是交互式的。” $-
似乎只是一个方便的指标,而不是定义的互动性。这与我的问题至关重要。
这两个(POSIXsh
定义和 Bash 的)都是机械定义,它们告诉您在什么情况下“交互式”标签适用于您启动的 shell。他们不是动作定义因为他们不给任何影响这个标签的。
然而,我发现 Bash 手册页的其余部分都散布着对 shell 以某些方式运行的引用,“除非它是交互式 shell”或“仅在交互式 shell 中,或者设置了 _____ 选项”。 (有很多例子,这不是这个问题的重点。)
因此,我接受“交互”只是一个方便的标签,用于在手册页的其余部分中描述的默认“交互”行为(选项设置)的集合。它本身不是一个基本术语或对象;它是一个基本概念。除了 shell 的源代码之外,它没有权威的定义。 (与“打开文件描述符”或“停止进程”等术语不同,它们指的是内核本身设计中内置的抽象。)
(虽然它也在 的 POSIX 定义中进行了定义sh
,但该手册页 [ man 1p sh
] 中“除非 shell 是交互式的”和类似语句的使用要少得多man bash
,并且几乎完全专注于调用时间差异,因此我将重点关注 Bash从现在开始。)
shell“交互式”的一些含义只是相关的在调用时无论如何,例如 shell 在读取其他命令之前会获取哪些文件。然而,有是任何时候都相关的含义(至少在 Bash 中)。因此,对于任何给定的情况,必须有一种方法来判断跑步shell,无论它是否是交互式的。
在交互式 Bash shell 中运行set +i
会导致 'i' 从$-
.
问题是:这实际上意味着 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.
严格阅读确切的定义也提出了一个问题:如果交互式终端的 stdin 或 stderr 被重定向,因此它们不再连接到终端,那么 shell 是否会变为非交互式?
(它出现这个问题的答案是“否”,手册页可以包含修饰符:“其标准输入和错误都连接到终端......在调用时,“但我不确定。)
如果答案是“不,shell 不能变得非交互式,反之亦然”,那么是什么确定的如何确定 shell 是否是交互式的?
换句话说:如果“交互式 shell”的行为在 后仍然存在set +i
,使用什么以确定这些行为应该继续适用?
免得有人怀疑:有是交互式调用的 shell 的行为在 后持续存在set +i
,非交互调用的 shell 的行为在 后持续存在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 和非交互式 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}
使用未设置参数的类似测试会产生类似的结果,再次确认这$-
不是 shell 交互性的“真相来源”。
所以,最后,shell 的明确“交互性”特征存储在哪里?
和,交互式 shell 可以变成非交互式 shell,反之亦然吗? (……通过改变这个特性?)
答案1
我要问的问题是为什么有人想要这样做?
您可以禁用交互式 shell 的某些方面,例如:
PS1= PS2=
禁用提示set +m
禁用作业控制- 在某些 shell 中禁用历史记录
- 您也许可以卸载
zle
中的 和所有完成模块zsh
。
但如果您希望 shell 停止交互,您可以这样做:
. /some/file; exit
告诉它从中获取其余命令(如果您仍然希望从 tty 设备读取命令,/some/file
请替换为),尽管与非交互式 shell 仍然存在一些差异,例如行为或事实它仍然会进行作业控制或:/dev/tty
return
exec myshell /dev/tty
将当前的交互式 shell 替换为仍从 tty 设备读取命令的非交互式 shell。
请注意,对于 bash 4.4,set +i
返回的结果与bash: set: +i: invalid option
大多数其他 shell 中类似。