我正在使用该script
命令将终端的所有输出保存到名为typescript
.或者script foo
保存到文件中foo
。
现在,假设我正在一个接一个地输入命令,但我忘记了我是否在打字稿中。
我怎样才能知道我是否在打字稿中?
答案1
也许与:
if lsof -tac script "$(tty)" > /dev/null; then
echo "I'm running under script"
else
echo "I'm not"
fi
你可以添加类似的内容:
lsof -tac script "$(tty)" > /dev/null && PS1="[script] $PS1"
到您的~/.zshrc
或~/.bashrc
,因此有关您是否在的信息script
将在您的 shell 提示符上可见。
或者,如果您不能保证lsof
安装,您可以这样做(假设未修改的 IFS):
terminal=$(ps -o comm= -p $(ps -o ppid= -p $(ps -o sid= -p "$$")))
[ "$terminal" = script ] && PS1="[script] $PS1"
启发式方法是获取会话领导者父级的命令名称,通常是终端仿真器(xterm
、script
、screen
...)。
答案2
有趣的问题。我发现一个小的 bash 脚本可以非常可靠地完成这项工作:
#!/bin/bash
PP=$(ps -o ppid= $$)
while [[ $PP != 1 ]]
do
LINE=$(ps -o ppid= -o comm= $PP | sed 's/^ *//')
COMM=${LINE#* }
PP=${LINE%% *}
if [[ $COMM == script ]] # Might need a different comparison
then
echo "In script"
exit 0
fi
done
echo "Not in script"
我认为这与 Stephane Chazelas 提出的略有不同,因为我的脚本按照 Linux/Unix 进程所具有的父:子关系向上工作,直到找到 PID 1,或者找到“脚本”作为进程。
答案3
如果您的路径中有个人 bin/ 目录(例如 /home/user/bin),请在其中放置一个名为“script”(与二进制文件同名)的 shell 脚本,其中包含以下内容:
#!/bin/bash
export SCRIPT_RUNNING=1
exec /usr/bin/script # full path to your script(1) binary
现在,在脚本运行中,您可以测试环境变量 SCRIPT_RUNNING,并根据它执行您想要的操作。
编辑:
实际上,还有一种更简单的方法。下面说明了一切,创建三个文件,~/bin/script、~/bin/script-shell 和~/.scriptrc:
~ > ls ~/bin/script ~/bin/script-shell ~/.scriptrc
-rw-r--r-- 1 roadowl users 23 Oct 18 16:52 /home/roadowl/.scriptrc
-rwx------ 1 roadowl users 49 Oct 18 16:53 /home/roadowl/bin/script
-rwx------ 1 roadowl users 56 Oct 18 16:55 /home/roadowl/bin/script-shell
~/bin > cat script
#!/bin/bash
exec /usr/bin/script -c script-shell
~/bin > cat script-shell
#!/bin/bash
exec /bin/bash --rcfile /home/bjd/.scriptrc
~/bin > cat ~/.scriptrc
export PS1="[script] "
如果您当前的 shell 是 bash,请不要忘记hash -r
在创建这些文件后运行,以确保在输入“script”作为命令时运行 ~/bin/script(使用 进行检查which script
)。
和以前一样,请注意,您的 PATH 中必须有 ~/bin,位于标准路径之前才能正常工作。
答案4
长话短说
对于本地主机上的大多数用例,检查脚本环境变量或预期输出文件的存在通常是最好的选择。然而,在许多用例中,您必须显式设置变量或信号量(本地或远程)、标记窗口(例如在 GNU screen 或 tmux 中)或终端选项卡,或者提出一些不依赖于可能不适用于您的特定情况的隐式或默认行为的其他解决方案。
我在下面提供了一些示例来说明如何检查脚本BSD 和 Linux 上的变量。我还提供了一些注意事项,包括通过 SSH 连接到远程主机时此方法的局限性。
BSD:检查脚本环境变量
在使用 BSD 版本的系统上script
,您可以检查是否存在脚本环境变量。 BSD 的脚本(1) 说:
SCRIPT 环境变量已添加到子 shell 中。如果 SCRIPT 已存在于用户环境中,则其值
例如,给定:
SHELL=/bin/sh script logfile.log
# script exports SCRIPT to sub-shells, so you can test if
# it's non-empty
[ -n "$SCRIPT" ] && echo "in typescript"
# SCRIPT holds the name of the typescript file you specified,
# or "typescript" by default; his enables you to check if
# you're in a *specific* typescript
[ "$SCRIPT" = "logfile.log" ] || [ "$SCRIPT" = "typescript" ]
# returns name of typescript file or an error message
echo "${SCRIPT?not in typescript}"
# exit status 0 in typescript; show error message and return
# exit status 1 outside the typescript
: "${SCRIPT?not in typescript}"
# this is less reliable, but can be useful in some cases;
# true if in a sub-shell, although there are no guarantees
# the sub-shell was spawned by script
[ "$SHLVL" -gt "1" ]
Linux:导出您自己的 SCRIPT 变量
util-linux 2.23.2 附带的版本(这是我方便的版本)默认情况下不导出 SCRIPT 变量。您可以简单地导出自己的文件,无论您使用 shell 的方式如何。在像 Bash 这样的 shell 中:
SCRIPT='typescript' script
然后您可以进行与上述相同的测试。
注意事项
该script
命令允许您指定要运行的命令,而不仅仅是启动 shell。因此,如果您的命令清理环境(例如env -i printenv
),取消设置 SCRIPT 变量,或者位于远程系统上(例如通过 SSH 登录),那么脚本不会传播。
如果您使用 SSH,您可以考虑使用以下命令传播它发送环境或者设置环境在客户端,以及接受环境在服务器端,但我不会依赖它,因为它不是大多数系统上的典型默认值。您也许还可以设置允许本地命令在服务器上并访问您的本地环境~C和!echo $SCRIPT
,但同样,除非您控制服务器,否则我不会依赖它。