为何Bash脚本在Ubuntu开机启动时无法运行?
我来帮你捋捋这个问题哈!先还原下你的场景:
你有个test.sh脚本,内容是这样的:
cd test-1 source .venv/bin/activate python test.py deactivate
在终端里你在用户主目录(~)下跑./test.sh完全没问题,但把这个命令加到Ubuntu的「启动应用程序首选项」里,开机后脚本就是不执行,而且你也明确说了,不是问怎么加开机启动,是好奇为啥启动程序里的命令和终端里敲的不一样才行。
核心原因:开机启动的执行环境和终端不一样!
最关键的差异就是工作目录(当前路径)不同:
- 你在终端里运行
./test.sh时,当前目录是你的用户主目录(比如/home/nick),所以./test.sh能精准找到这个脚本,后面的cd test-1也是基于主目录去找这个子文件夹。 - 但Ubuntu的「启动应用程序」在执行命令时,默认的工作目录并不是你的用户主目录,大概率是系统根目录
/或者其他系统级路径,这时候./test.sh就相当于在/下去找这个脚本,肯定找不到,脚本自然跑不起来;就算脚本能找到,后面的cd test-1也会因为当前路径不对,找不到这个文件夹。
除此之外,还有个小问题:开机启动的环境变量集合和终端登录后的环境变量不一样,比如你终端里能直接用python调用虚拟环境里的Python,但开机启动时可能只会找系统默认的Python,也会导致脚本执行失败。
解决办法(给你几个靠谱的选项)
选项1:用绝对路径指定脚本
把启动应用程序里的命令改成脚本的绝对路径,比如你的test.sh在/home/nick/test.sh,那命令就写:/home/nick/test.sh这样不管当前工作目录是啥,系统都能精准找到你的脚本。
选项2:在脚本开头自动切换到正确路径
给你的test.sh加个“自定位”的开头,让脚本自己切换到它所在的目录,这样不管在哪里执行都不会出错:# 先切换到脚本所在的目录 cd "$(dirname "$0")" # 原来的脚本内容 cd test-1 source .venv/bin/activate python test.py deactivate这里的
"$(dirname "$0")"会自动获取脚本本身所在的文件夹路径,cd过去之后,后面的相对路径就都能正常工作了。选项3:把所有相对路径改成绝对路径
把脚本里的所有相对路径都换成绝对路径,比如:cd /home/nick/test-1 source /home/nick/test-1/.venv/bin/activate /home/nick/test-1/.venv/bin/python /home/nick/test-1/test.py deactivate这种方式最“直白”,完全避免了路径相关的坑,适合怕麻烦的情况。
额外小提示
如果还是有问题,可以给脚本加个日志输出,方便排查哪里出错了,比如把启动命令改成:
/home/nick/test.sh > /home/nick/test_startup.log 2>&1
这样脚本执行的所有输出(包括错误信息)都会写到test_startup.log里,打开日志就能看到具体是哪一步出问题了。
备注:内容来源于stack exchange,提问作者Paul Jurczak

