I am creating a command that will change a certain line in the /etc/profile
file from a script, however in certain versions of Linux the sudo
command may not be activated so it would be necessary to use the su
command for this, within the script when executing:
Inside the /etc/profile
file there is the following line:
if [ "`id -u`" = "0" ]; then
echo $PATH | grep /usr/local/sbin 1> /dev/null 2> /dev/null
if [ ! $? = 0 ]; then
PATH=/usr/local/sbin:/usr/sbin:/sbin:$PATH
fi
fi
So I did this:
$ PROFILE="/etc/profile"
$ sed '/\"`id -u`\"/ s/^if/# if/g;/\"`id -u`\"/ s/$/\nif [[ \"\$(id -u)\" == \"0\" || \"\$(id -un)\" == \"\${HOME##*\/}\" ]]; then/g;' ${PROFILE}
# if [ "`id -u`" = "0" ]; then
if [[ "$(id -u)" == "0" || "$(id -un)" == "${HOME##*/}" ]]; then
echo $PATH | grep /usr/local/sbin 1> /dev/null 2> /dev/null
if [ ! $? = 0 ]; then
PATH=/usr/local/sbin:/usr/sbin:/sbin:$PATH
fi
fi
The command appeared to execute correctly to change the file but when doing so using the su -c
command:
$ PROFILE="/etc/profile"
$ su -c "sed '/\"`id -u`\"/ s/^if/# if/g;/\"`id -u`\"/ s/$/\nif [[ \"\$(id -u)\" == \"0\" || \"\$(id -un)\" == \"\${HOME##*\/}\" ]]; then/g;' ${PROFILE}"
if [ "`id -u`" = "0" ]; then
echo $PATH | grep /usr/local/sbin 1> /dev/null 2> /dev/null
if [ ! $? = 0 ]; then
PATH=/usr/local/sbin:/usr/sbin:/sbin:$PATH
fi
fi
It asks for the password and reads the file in the $PROFILE
variable but does not modify the line. What is the problem with the su -c
command?
Best Answer
N.B: All code was tested in a Slackware64 15.0 VM.
Literal answer
As @ilkkachu noted, in the second form of the command (using su(1)) you are using the single quotes inside of the double quotes. Single and double quotes follow different rules; also see [1] and [2]. Also, only one regex is necessary.
As @waltinator reminded, you should keep backups of any important modified files, which /etc/profile is. GNU sed has
-i
option to create backups, which regrettably isn't portable, so the alternative is to first create a backup copy of the modified file, and then operate on that backup copy and redirect stdout to the new file.So, your command should be:
However, to stay compliant to POSIX sh(1p) (also: [3]), you should avoid non-POSIX constructs, such as
Instead, you can use
like this:
You can also avoid executing su altogether to change /etc/profile, if the file /etc/profile.bak already exists:
The alternative (correct) approach
From the comments, it seems that what you are actually trying to do is to automate the creation of user accounts which would be able to use sudo(8) and also have
/usr/local/sbin:/usr/sbin:/sbin
prepended to theirPATH
. This can easily be achieved without changing such a vital system file as /etc/profile.In order to do that, you should:
createuser
, which accepts username as first argument, let's call itnewuser
) to automate the creation of users, this can be substituted by passing it to sudo or su, eg.su -c 'createuser newuser'
.newuser
to /etc/sudoers, so it can execute sudo to obtain root privileges:Inside of a script, this will be a bit different. If you have saved the username in a variable
user
:/usr/local/sbin:/usr/sbin:/sbin
toPATH
in /home/newuser/.profile to customize his environment:newuser
(needs tty to change password):or set it to "expired", which will force the user to set it on next login, and doesn't require a tty:
Addendum
PATH
inside of an environment created by executing sudo, see How to makesudo
preserve $PATH?. Note that no additional steps other than the ones from the "alternative approach" above are necessary by default in Slackware64 15.0:or, if you want to not "hard-code" the username, but use the current username:
Again, mind the quotes, single-quotes and backslash-escapes and how they relate to each other. See the references for more information.
PATH
in the existing session by modifying $HOME/.profile to include setting it to a new value, logically, requires either re-sourcing $HOME/.profile after modification:or relogging.
References
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02
https://www.gnu.org/software/bash/manual/html_node/Quoting.html
https://pubs.opengroup.org/onlinepubs/9699919799/idx/shell.html