如何在Bash执行的脚本Shebang中设置环境变量?及异常原因分析
在Shebang中设置环境变量的正确方式及问题排查
嘿,我来帮你把这个问题掰明白——先讲清楚怎么在shebang里给解释器设置环境变量,再拆解你遇到的脚本挂起的原因:
正确设置环境变量的shebang写法(针对主流Linux系统)
如果你的系统用的是GNU版本的env(绝大多数Linux发行版都是),可以用-S选项让env正确拆分参数:
#!/usr/bin/env -S TEST=TEST python print('hello')
-S的作用是告诉env把后面的字符串按空格拆成多个独立参数,这样TEST=TEST会被当作环境变量设置,python才会被识别为要启动的解释器。
为什么你的第一种写法会挂起?
核心问题出在内核解析shebang的规则上:
- 当你写
#!/usr/bin/env TEST=TEST python时,内核会把#!后面的内容拆成两部分:第一部分是解释器路径/usr/bin/env,第二部分是一整个字符串参数TEST=TEST python(注意,这里是一个参数,不是两个!)。 - 这时候
env收到的是一个完整的参数TEST=TEST python,它没法识别这是“环境变量+命令”的组合,反而会把这个整个字符串当作要执行的命令名去系统里找——显然不存在叫TEST=TEST python的命令,这就导致进程卡住(也就是你看到的挂起),直到你用^C终止。
为啥另外两种写法能正常运行?
#!/usr/bin/env python:
内核把python作为单个参数传给env,env会在系统PATH里找到python命令并启动它,然后把你的脚本文件作为参数传给Python解释器,自然能正常执行代码。命令行执行
/usr/bin/env TEST=TEST python hello.py:
这时候是shell在解析命令,它会自动把TEST=TEST、python、hello.py拆成三个独立参数传给env。env一眼就认出TEST=TEST是环境变量设置,接着执行python hello.py,所以全程顺畅。
兼容老系统的替代方案
如果你的系统(比如某些BSD)不支持env -S,可以换用bash的shebang间接实现:
#!/bin/bash export TEST=TEST exec python "$0" "$@" print('hello')
这个写法的逻辑是:先让bash执行开头的两行代码,设置环境变量后用exec把当前bash进程替换成Python进程,同时把脚本本身($0)和传入的参数($@)传给Python,这样后面的Python代码就能正常运行了。
内容的提问来源于stack exchange,提问作者Fredrick Brennan
相关产品推荐
相关产品推荐

