You wrote
My goal is to write something to a file that needs superuser permission
One way to do this is to relax the permissions on the file so that it has (for example) group write permission. Then add the relevant users to that group. After a logout/login they will then be able to write to the file with no need for sudo
.
Another "proper" way to do this with sudo
is to create a script that manages the writing process, and then authorise that script within /etc/sudoers
so that selected users don't need to provide a password. The big advantage of this is that the target file is not freely accessible even to your target users; your script can validate and sanitise the input before it's written to the file
Get a root shell. Keep this open and do not close it until you are sure that sudo
is still working
sudo -s
Now create the script
cat >/usr/local/bin/write-to-file <<'EOF'
#!/bin/bash
#
export PATH=/usr/local/bin:/usr/bin:/bin # Only necessary for a non-standard PATH
Restart with sudo if we are not already root
[[ $(id -u) != 0 ]] && exec sudo "$0" "$@"
Read just one line into the target file
head -n1 >/etc/test.txt
EOF
Still using this root shell, make the script executable and then add a line to sudoers
. Change the inital user
to the user account that is permitted to run write-to-file
without a password, or ALL
if any user is allowed.
chown root /usr/local/bin/write-to-file # Ensure no-one else can modify the script
chmod a+rx,go-w /usr/local/bin/write-to-file # Make it executable
echo 'user ALL = NOPASSWD: /usr/local/bin/write-to-file' >/etc/sudoers.d/write-to-file
Do not close the root shell yet.
In another (non-root) terminal, test the new script. If you get write-to-file: command not found
then /usr/local/bin
isn't in your PATH (run export PATH="$PATH:/usr/local/bin"
)
echo hello | write-to-file # Should not prompt for password
cat /etc/test.txt # Should contain "hello"
write-to-file < /etc/passwd # Multiline input
cat /etc/test.txt # Contains only the first line from passwd
Notice that we didn't even need to use sudo
here. What's happened is that the script noticed it wasn't running as root, and restarted itself with sudo
.