Timeline for Executing a Bash Script Function with Sudo
Current License: CC BY-SA 3.0
24 events
| when toggle format | what | by | license | comment | |
|---|---|---|---|---|---|
| Feb 10, 2023 at 11:10 | comment | added | Randyman99 | I tried this and it worked, with some quirks. I adapted a script for testing spawning functions so the spawned function was run as root. The child process wasn't able to read input data from the keyboard. I couldn't issue a CTRL-C to kill the child process. I had the parent process attempt to kill it, and while this worked for an ordinary spawned child process, it did not work for one invoked by root, even preceding the kill command with sudo, tho I could let the parent process exit and then do a sudo kill on the child process, or from another window. My method below doesn't have these quirks. | |
| Dec 11, 2020 at 16:53 | comment | added | Aaron D. Marasco | I was able to get this to work but needed another exporting for that bash to export it to its children: sudo bash -c "$(declare -f myfunc); typeset -fx myfunc; mycommand" | |
| Mar 22, 2020 at 21:30 | comment | added | Dima Korobskiy | WARNING: the solution for aliasing this like I suggested above. e.g. alias lu="bash -c ' $(declare -f __lu_fn); __lu_fn \"\$@\" ' -" gets killed if the function code uses single quotes. More time has to be spend to find an aliasing solution tolerant to them. | |
| Dec 16, 2019 at 21:32 | comment | added | Dima Korobskiy | Additional care requires for passing arguments to functions, especially in conjunction with using aliases. I had to spend some time to figure this out, but it worked out in the end. For example: # Disk usage summary lu_fn() { if [[ $# -lt 1 ]]; then local args='.' else local args=( "$@" ) fi du -hxd1 "${args[@]}" | sort -hr } # shellcheck disable=SC2142 # shellcheck disable=SC2139 alias lu="bash -c '$(declare -f lu_fn); lu_fn \"\$@\"' -" | |
| Feb 10, 2017 at 12:38 | comment | added | GrayedFox | Excellent answer. I implemented your solution - I would note that you can import the script itself from within the script, provided you nest it within an conditional which checks if against sudo yourFunction being found (otherwise you get a segmentation error from the recursion) | |
| Mar 13, 2016 at 7:42 | vote | accept | BryKKan | ||
| Mar 11, 2016 at 23:07 | comment | added | Gilles 'SO- stop being evil' | @cas On the contrary, no changes are necessary. I suggest you experiment a little to see what's going on. | |
| Mar 11, 2016 at 22:54 | comment | added | cas | @Gilles - That's a) not documented in bash's man or info pages and b) not what it looks like. FUNC=$(declare -f hello) ; echo $FUNC shows no changes to the quotes in the function...and those changes are necessary if $FUNC is going to used inside double-quotes. | |
| Mar 11, 2016 at 19:58 | history | edited | Gilles 'SO- stop being evil' | CC BY-SA 3.0 | added 131 characters in body |
| Mar 11, 2016 at 19:57 | comment | added | Gilles 'SO- stop being evil' | @BryKKan You can export all functions with declare -f. | |
| Mar 11, 2016 at 19:57 | comment | added | Gilles 'SO- stop being evil' | @cas declare -f prints out the function definition in a way that can be re-parsed by bash, so bash -c "$(declare -f)" does work correctly (assuming that the outer shell is also bash). The example you posted shows it working correctly — where the quotes were changed is in the trace, because bash prints out traces in shell syntax, e.g. try bash -xc 'echo "hello world"' | |
| Mar 11, 2016 at 12:15 | comment | added | cas | Note how it changed the single-quotes to '\'' and double-quotes to single-quotes. BTW, the quotes are being changed by the parent shell, not by the bash -xc child shell. zsh does pretty much the same and even dash does it. ksh needs typeset -f rather than declare -f. i didn't put in too much effort but ash doesn't seem to do it (and doesn't have declare or typeset anyway). | |
| Mar 11, 2016 at 12:07 | comment | added | cas | i did some testing earlier this afternoon (using bash -xc rather than just bash -c) and it looks like bash is smart enough to re-quote things in this situation, even to the extent of replacing double-quotes with single quotes and changing ' to '\'' if necessary. I'm sure there will be some cases it can't handle, but it definitely works for at least simple and moderately complex cases - e.g. try function hello() { filename="this is a 'filename' with single quotes and spaces" ; echo "$filename" ; } ; FUNC=$(declare -f hello) ; bash -xc "$FUNC ; hello" | |
| Mar 11, 2016 at 6:20 | comment | added | BryKKan | This does answer the original question, so if I don't get a better solution I'll accept it. However, it does break my particular function (see my edit) since it's dependent on functions defined elsewhere in the script. | |
| Mar 11, 2016 at 5:45 | comment | added | Will | export -f seems to handle the quoting well, though. See my edit. Please pastebin me an example where this breaks. | |
| Mar 11, 2016 at 5:38 | comment | added | cas | try reading what i said and think it through. your example really does only work by accident (i.e. the fact that the double-quotes have no significant effect in this particular echo command). In other cases, where the double-quotes have a significant effect, they will break the bash -c command and the sudo. | |
| Mar 11, 2016 at 5:36 | comment | added | Will | @cas Test it. See my edit. It does not work "by accident". | |
| Mar 11, 2016 at 5:35 | history | edited | Will | CC BY-SA 3.0 | added 330 characters in body |
| Mar 11, 2016 at 5:34 | comment | added | cas | you misunderstand what i said. the double-quotes don't make this work. they have the potential to cause it to NOT work and it's only by accident that this particular echo command works the same with or without double quotes that allows it to work. | |
| Mar 11, 2016 at 5:33 | comment | added | cas | yes, exactly. that's the source of the problem. because you're wrapping the bash -c command in double-quotes, you now have double-quotes inside double-quotes. without careful escaping, quotes don't nest, they toggle. | |
| Mar 11, 2016 at 5:33 | comment | added | Will | @cas The only issues that would arise are if something in the function actually needs to be quoted. I always quote string arguments out of habit; the quotes around echo's arguments have nothing to do with how or why this works. | |
| Mar 11, 2016 at 5:27 | comment | added | Wildcard | @cas, are you sure about that? When I run declare -f functionname on a function I have defined in my shell, I see the double quotes output just as they were when I defined them. | |
| Mar 11, 2016 at 5:21 | comment | added | cas | This only works by accident, because echo "Hello!" is effectively the same as echo Hello! (i.e. double-quotes make no difference for this particular echo command). In many/most other circumstances, the double-quotes in the function are likely to break the bash -c command. | |
| Mar 11, 2016 at 5:13 | history | answered | Will | CC BY-SA 3.0 |