如何通过`sudo -s`传递含美元符号的变量至Shell子脚本?
解决包含美元符号的参数在sudo -s调用子脚本时被解析的问题
这个问题的核心是sudo -s会启动一个新的shell进程,它会对传递的参数进行二次解析,导致原字符串中的$被当作变量展开,最终丢失了原有的内容。下面是两种可行的解决方法:
方法一:移除不必要的sudo -s
如果你的场景不需要启动登录shell(-s参数的作用),直接用sudo执行子脚本即可,这样参数会直接传递,不会被额外解析:
修改test.sh为:
#! /bin/sh echo "test arguments: $@" variable=$1 sudo -u $USER ./subtest.sh "$variable"
这种方法最简单,也是最推荐的,因为-s通常用于需要加载用户环境变量的场景,如果只是执行一个脚本,完全不需要它。
方法二:对参数进行shell转义(必须用sudo -s时)
如果因为某些原因必须保留sudo -s,我们需要把参数转义成shell无法解析的格式,确保原字符串完整传递。可以用printf "%q"来实现自动转义:
修改test.sh为:
#! /bin/sh echo "test arguments: $@" variable=$1 sudo -u $USER -s ./subtest.sh "$(printf "%q" "$variable")"
printf "%q"会把输入的字符串转义成适合shell作为参数的格式,比如abc$def会被转义成abc\$def,这样新启动的shell就不会把$def当作变量展开,而是保留原有的$符号。
为什么原来的写法会失效?
当你用sudo -s ./subtest.sh "$variable"时,sudo会启动一个新的shell,然后把./subtest.sh "$variable"作为命令传递给这个新shell。此时新shell会重新解析这个命令字符串:如果variable的值是abc$def,新shell会尝试展开$def(而这个变量在新shell中不存在,会被替换为空),最终传递给subtest.sh的参数就变成了abc,而非原字符串。
内容的提问来源于stack exchange,提问作者natevw
相关产品推荐
相关产品推荐

