Running commands in a script as another user using a here doc
Asked Answered
R

1

5

I want to be able to switch users in the middle of a script. Here is one attempt:

su - User << EOF

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" </dev/null

EOF

My goal is to execute the code between the EOF delimiters as if I actually logged in as User.

The middle line is supposed to install Homebrew. If I log in as User and run the middle line on its own, it installs fine. But running the full script above gives me problems:

-e:5: unknown regexp options - lcal
-e:6: unknown regexp options - lcal
-e:8: unknown regexp options - Cach
-e:9: syntax error, unexpected tLABEL
BREW_REPO = https://github.com/Homebrew/brew.freeze
                  ^
-e:9: unknown regexp options - gthb
-e:10: syntax error, unexpected tLABEL
CORE_TAP_REPO = https://github.com/Homebrew/homebrew-core.freeze
                      ^
-e:10: unknown regexp options - gthb
-e:32: syntax error, unexpected end-of-input, expecting keyword_end
-bash: line 34: end: command not found
-bash: line 36: def: command not found
-bash: line 37: escape: command not found
-bash: line 38: end: command not found
-bash: line 40: syntax error near unexpected token `('
-bash: line 40: `  def escape(n)'

I've tried a could different commands instead of just the Homebrew install but have problems most of the time. What is the difference between passing a command to 'su' as I am trying to do and actually running the command as that user?

Rolling answered 21/7, 2017 at 18:41 Comment(1)
Can you not user "sudo -u" for this?Zamarripa
D
6

What is happening is, the embedded $(...) command gets executed before the here-document is passed to su. That is, the actual script that is passed to su is something more like this:

/usr/bin/ruby -e "#!/System/Library/Frameworks/Ruby.framework/Versions/Current/usr/bin/ruby
# This script installs to /usr/local only. To install elsewhere you can just
# untar https://github.com/Homebrew/brew/tarball/master anywhere you like or
# change the value of HOMEBREW_PREFIX.
HOMEBREW_PREFIX = "/usr/local".freeze
HOMEBREW_REPOSITORY = "/usr/local/Homebrew".freeze
HOMEBREW_CACHE = "#{ENV["HOME"]}/Library/Caches/Homebrew".freeze
...

And so on. In other words, the output of $(...) got inserted into the here-document.

To avoid that, you need to escape the $:

su - User << EOF

/usr/bin/ruby -e "\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" </dev/null

EOF

Alternatively, you can tell the shell to treat the entire here-document literally without any interpolation, by enclosing the starting EOF within double-quotes:

su - User << "EOF"

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" </dev/null

EOF
Devaughn answered 21/7, 2017 at 18:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.