转义 bash 函数参数以供 su -c 使用

Posted

技术标签:

【中文标题】转义 bash 函数参数以供 su -c 使用【英文标题】:Escaping bash function arguments for use by su -c 【发布时间】:2012-09-02 19:41:06 【问题描述】:

我希望能够编写一个函数 su_mt_user,它(目前)看起来像这样:

su_mt_user() 
    su someuser -c "$*"

目标是能够像这样使用它:

su_mt_user mt-auth --stuff etc

它将以用户someuser 的身份运行命令mt-auth --stuff etc。当前版本适用于这个特定的命令,但对于这样的命令却失败了:

some_filename_with_spaces="/home/user/hello there i like spaces in filenames.txt"
su_mt_user stat "$some_filename_with_spaces"

这会失败并出现以下错误:

stat: cannot stat '/home/user/hello': No such file or directory
stat: cannot stat 'there': No such file or directory
stat: cannot stat 'i': No such file or directory
stat: cannot stat 'like': No such file or directory
stat: cannot stat 'spaces': No such file or directory
stat: cannot stat 'in': No such file or directory
stat: cannot stat 'filenames.txt': No such file or directory

我认为发生此错误是因为即使 $some_filename_with_spaces 被正确地作为一个参数传递给 su_mt_user 函数,该函数将其扩展为带有 "$*" 的多个参数。

我也试过这个,反复试验:

su_mt_user() 
    su someuser -c "$0 $@"

但这也失败了(/usr/bin/stat: cannot execute binary file(什么?))

当然,stat "$some_filename_with_spaces" 在当前用户和someuser 用户中都按预期工作。

这看起来需要进行一些转义,但是 bash 知道该怎么做吗?需要手动替换吗?如果是,哪些字符需要转义?

【问题讨论】:

【参考方案1】:

要通过函数将多个参数传递给命令,您需要"$@""$@" 的特殊之处在于,即使它在双引号之间,单独的参数也会以不同的单词结尾,因此它们会按原样传递。这与不带引号的$@$* 不同,后者将另外拆分包含空格的每个参数并将每个结果单词解释为全局模式,而"$*" 将所有参数合并为一个带有空格的参数介于两者之间。

还有一个额外的问题,因为su 不会直接吃掉参数,它们会通过外壳。 su 的非选项参数作为参数传递给sh -c,然后您需要为-c 提供适当的命令。

su_mt_user() 
    su someuser -c '"$0" "$@"' -- "$@"

【讨论】:

谢谢!必须通过添加-- 来对其进行一些修改以防止su 也解析选项参数:su someuser -c '"$0" "$@"' -- "$@";否则,su 会尝试将像 -a 这样的选项参数解释为自身的参数,从而导致错误。 我还必须将其修改为su someuser -c '"$0" "$@"' -- "$0" "$@",因为命令/bin/su -l root -c 'echo args "$@" this "$0"' -- a b c 显示args b c this a

以上是关于转义 bash 函数参数以供 su -c 使用的主要内容,如果未能解决你的问题,请参考以下文章

是否可以保存带有参数的函数指针以供以后使用?

如何将 url 参数传递给视图以供其他类函数和模板使用

Perl:转义字符串中的特殊字符以匹配正则表达式

转义闭包捕获非转义参数“函数” Xcode 说

JavaScript 函数参数中的单引号转义

如何使用参数制作 Bash 函数? [复制]