我有一个脚本,我写的是切换到root或以root身份运行命令而没有密码.我编辑了我的/ etc/sudoers文件,以便我的用户[matt]有权运行/ bin/su而没有密码.这是我的脚本"s"内容:
matt: ~ $ cat ~/bin/s
#!/bin/bash
[ "$1" != "" ] && c='-c'
sudo su $c "$*"
如果没有参数[简单s],它基本上调用sudo su哪个没有密码进入root.但是如果我输入参数,$ c变量等于"-c",这使得su执行单个命令.
它工作得很好,除了我需要使用空格.例如:
matt: ~ $ touch file\ with\ spaces
matt: ~ $ s chown matt file\ with\ spaces 
chown: cannot access 'file': No such file or directory
chown: cannot access 'with': No such file or directory
chown: cannot access 'spaces': No such file or directory
matt: ~ $ s chown matt 'file with spaces'
chown: cannot access 'file': No such file or directory
chown: cannot access 'with': No such file or directory
chown: cannot access 'spaces': No such file or directory
matt: ~ $ s chown matt 'file\ with\ spaces'
matt: ~ $ 
我怎样才能解决这个问题?
另外,$*和$ @之间有什么区别?
啊,引用有趣.通常,@ John建议采用的方法是:使用"$@",并且它不会试图解释(并且混淆)参数中的空格和其他有趣的字符.但是,在这种情况下,这将无法工作,因为su的-c选项需要将整个命令作为单个参数传递,然后它将启动一个解析命令的新shell(包括被空格等混淆) .为了避免这种情况,您实际上需要重新引用要传递给的字符串中的参数su -c.bash的printf内置可以做到这一点:
#!/bin/bash
if [ $# -gt 0 ]; then
    sudo su -c "$(printf "%q " "$@")"
else
    sudo su
fi
让我回顾一下这里发生的事情:
s chown matt file\ with\ spacesprintf "%q " "$@"在脚本中解析命令时,它将替换脚本"$@"的参数,参数分解完整.它相当于printf "%q " "chown" "matt" "file with spaces".printf将格式字符串"%q"解释为"以引用形式打印每个剩余参数,后面带一个空格".它打印:"chown matt file\with\spaces",基本上重建原始命令行(它在末尾有一个额外的空间,但事实证明这不是一个问题).$()构造周围有双引号,它将被视为sudo的单个参数).这相当于跑步sudo su -c "chown matt file\ with\ spaces ".sudo运行su,并传递它获得的参数列表的其余部分,包括完全转义的命令.su 运行一个shell,它还传递其参数列表的其余部分.-c:chown matt file\ with\ spaces.在解析它的正常过程中,它将非转义空间解释为参数之间的分隔符,将转义空格解释为参数的一部分,并且它将忽略末尾的额外空间.chown,参数为"matt"和"带空格的文件".这符合您的期望.不是bash解析hoot?