如何检查脚本是通过命令行执行还是双击执行的?

如何检查脚本是通过命令行执行还是双击执行的?

如何确定脚本是从命令行调用还是通过文件管理器(Nautilis)双击调用?

如果是前者,脚本执行完毕后仍会出现命令提示符,但如果双击脚本(或通过 .desktop 文件执行),脚本会在窗口中执行,然后消失。我希望窗口保持打开状态并显示命令提示符。

我认为该脚本可以进行此项检查,并且如果从命令行调用则不执行任何操作,或者exec如果通过双击或.desktop 调用则在最后执行 bash。

使用各种方法检查是否为交互式或 tty 均未成功。

答案1

您可以检查父进程是否是 shell。例如:

#! /bin/bash

if [[ $(readlink -f /proc/$(ps -o ppid:1= -p $$)/exe) != $(readlink -f "$SHELL") ]]
then 
    echo "Starting the shell..."
    exec "$SHELL"
else
    echo "Not starting a shell."
fi

ps -o ppid:1= -p $$ppid打印当前进程( ) 的父进程 ( ) 的 PID -p $$readlinkon/proc/<pid>/exe应该打印可执行文件的路径,如果您在 shell 中运行它,则该路径将是 shell,否则将是其他路径。


另一种可能性是变量SHLVL,表示当前 shell 实例的嵌套程度。如果在 shell 中运行,脚本应该有SHLVL2 个或更多。通过双击或从桌面启动器运行时,它应该是 1:

#! /bin/bash

if (( SHLVL > 1 ))
then 
    echo "Starting the shell..."
    exec "$SHELL"
else
    echo "Not starting a shell."
fi

答案2

您可以通过分析以下输出来检查 shell 脚本是否在终端上运行:终端命令。

#! /bin/bash

if [[ $(tty) =~ "not a tty" ]]
then
    echo "Not running on terminal"

else
    echo "Running on terminal"
fi

答案3

从 Nautilus 双击时,您不会像在常规终端会话中那样设置整个环境。我使用这个样板代码来防止崩溃:Bash 脚本的桌面快捷方式崩溃并烧毁。您可以根据自己的需要进行调整:

# $TERM variable may be missing when called via desktop shortcut
CurrentTERM=$(env | grep TERM)
if [[ $CurrentTERM == "" ]] ; then
    notify-send --urgency=critical "$0 cannot be run from GUI without TERM environment variable."
    exit 1
fi

答案4

我检查了从终端运行脚本时的环境与在文件中双击运行脚本时的环境之间的差异;

当您通过双击文件来运行脚本时,该$VTE_VERSION变量未设置,因此您可以挂钩它来决定是否用交互式实例替换当前的 Bash 实例。

也就是说,只需将其放在脚本的末尾:

#! /bin/bash
# ...
[ ! -z $VTE_VERSION ] && exec bash

为了使此脚本在从桌面文件运行的情况下也能正常工作,请将桌面文件的 Exec= 行从以下行更改为:

Exec=/path/to/script

到:

Exec=sh -c '/path/to/script; exec bash'

这种方式/path/to/script将被执行,并在完成后被shBash 替换。/path/to/script

相关内容