Bash中runuser存入变量执行带参数脚本失败的解决问询
问题:Bash中runuser执行带参数脚本时的引号解析错误
需求:编写Bash脚本,判断当前用户是root还是非root,以对应身份执行带参数的目标脚本并检查执行结果。但使用runuser时,将命令存入变量后执行,Bash无法正确识别引号,导致runuser误将目标脚本的参数-s当作自身参数,报错:
runuser: option requires an argument -- 's'
原问题代码
#!/bin/bash check_other_script(){ user=mruser bin_dir=/home/$user/bin script_name=myscript decho "[d] Performing $script processing of settings check" sub_cmd="${bin_dir}/${script_name} -s" if [ "$running_user_type" == "root" ]; then #cmd="runuser -l $user -c "$sub_cmd"" elif [ "$running_user_type" == "non-root" ]; then cmd="$sub_cmd" fi decho "[d] command to run: $cmd" $cmd status="$?" decho "[d] script status code: $status." } check_other_script exit 0
错误原因
将完整命令存入普通字符串变量后,Bash执行$cmd时会进行单词拆分,完全忽略字符串内的引号边界。比如你尝试的各种引号写法,最终展开后runuser会把/home/mruser/bin/myscript当作-c的唯一参数,而-s会被当成runuser自身的命令行参数,触发参数解析错误。
正确实现方式
方法1:使用数组存储命令(推荐)
Bash数组可以精准保留每个参数的边界,避免单词拆分问题:
#!/bin/bash check_other_script(){ user=mruser bin_dir=/home/$user/bin script_name=myscript decho "[d] Performing $script processing of settings check" sub_cmd="${bin_dir}/${script_name} -s" if [ "$running_user_type" == "root" ]; then # 数组每个元素对应一个命令参数 cmd=(runuser -l "$user" -c "$sub_cmd") elif [ "$running_user_type" == "non-root" ]; then cmd=("$sub_cmd") fi decho "[d] command to run: ${cmd[*]}" # 用数组展开方式执行,保留参数边界 "${cmd[@]}" status="$?" decho "[d] script status code: $status." } check_other_script exit 0
方法2:直接执行,不存入变量
如果逻辑简单,可直接在分支内执行命令,规避变量存储带来的解析问题:
#!/bin/bash check_other_script(){ user=mruser bin_dir=/home/$user/bin script_name=myscript decho "[d] Performing $script processing of settings check" sub_cmd="${bin_dir}/${script_name} -s" if [ "$running_user_type" == "root" ]; then runuser -l "$user" -c "$sub_cmd" elif [ "$running_user_type" == "non-root" ]; then "$sub_cmd" fi status="$?" decho "[d] script status code: $status." } check_other_script exit 0
方法3:使用eval(不推荐)
eval可强制重新解析引号,但存在安全风险(若变量包含恶意内容会被执行),仅在可控场景下使用:
#!/bin/bash check_other_script(){ user=mruser bin_dir=/home/$user/bin script_name=myscript decho "[d] Performing $script processing of settings check" sub_cmd="${bin_dir}/${script_name} -s" if [ "$running_user_type" == "root" ]; then cmd="runuser -l $user -c \"$sub_cmd\"" elif [ "$running_user_type" == "non-root" ]; then cmd="$sub_cmd" fi decho "[d] command to run: $cmd" eval "$cmd" status="$?" decho "[d] script status code: $status." } check_other_script exit 0
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

