简体   繁体   English

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

[英]Escaping bash function arguments for use by su -c

I'd like to be able to write a function su_mt_user that (currently) looks like this: 我希望能够编写一个函数su_mt_user (当前)看起来像这样:

su_mt_user() {
    su someuser -c "$*"
}

The objective is to be able to use it like this: 目标是能够像这样使用它:

su_mt_user mt-auth --stuff etc

Which would run the command mt-auth --stuff etc as user someuser . 哪个将以用户someuser运行命令mt-auth --stuff etc The current version works for this particular command, but it fails for commands like this: 当前版本适用于此特定命令,但对于以下命令失败:

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

This fails with the following errors: 此操作失败,并出现以下错误:

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

I assume that this error happens because even though $some_filename_with_spaces is properly passed as one argument to the su_mt_user function, that function expands it to multiple arguments with "$*" . 我假设发生此错误是因为即使$some_filename_with_spaces作为一个参数正确传递给su_mt_user函数,该函数su_mt_user将其扩展为带有"$*"多个参数。

I've also tried this, trial-and-error: 我也试过这个,试错了:

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

But that fails as well ( /usr/bin/stat: cannot execute binary file (what?)) 但那也失败了( /usr/bin/stat: cannot execute binary file (什么?))

Of course, stat "$some_filename_with_spaces" works as expected, from both the current user and the someuser user. 当然, stat "$some_filename_with_spaces"可以从当前用户和someuser用户按预期工作。

This looks like some escaping needs to be done, but does bash know how to do that? 这看起来像是需要做一些逃避,但是bash知道如何做到这一点吗? Does it need manual subtitution? 是否需要手动替代? If so, which characters need to be escaped? 如果是这样,哪些角色需要转义?

To pass multiple arguments through a function to a command, you need "$@" . 要通过函数将多个参数传递给命令,需要"$@" "$@" is special in that even though it's between double quotes, the separate arguments end up in different words, so they're passed down exactly as is. "$@"的特殊之处在于即使它在双引号之间,单独的参数也以不同的词结尾,所以它们完全按原样传递。 This is different from $@ or $* without quotes, which would additionally split each argument where it contains whitespace and interpret each resulting word as a glob pattern, and from "$*" , which coalesces all arguments into a single one with spaces in between. 这与带有引号的$@$*不同,后者会将每个参数拆分为包含空格并将每个结果单词解释为glob模式,并从"$*"中将所有参数合并为一个带有空格的单个参数。之间。

There's an added wrinkle because su doesn't directly eat up arguments, they go through a shell. 还有一个额外的皱纹,因为su不直接吃掉论点,它们通过一个shell。 The non-option arguments to su are passed down as arguments to sh -c , and you then need an appropriate command for the -c . su的非选项参数作为参数传递给sh -c ,然后您需要为-c提供适当的命令。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM