How to check if command exists for a user? - bash

I install Pip for a user (not system wide) and I would like to check that pip is installed for that user in my script that I run with sudo: sudo ./script.sh
I know to check for a command with command -v pip3 and that works when I enter it in the shell as the user.
But how can I check it in my script?
command -v pip3 exit code is 1 because I am root (because of sudo).
su -c "command -v pip3" "$SUDO_USER" has exit code 1.
sudo -u "$SUDO_USER" command -v pip3 says "command: command not found"

The simplest is
sudo -u "$SUDO_USER" -i command -v pip3
The -i option causes sudo to pass the supplied command line to the user's configured shell using its -c option, instead of trying to execute the command directly. That's necessary because command is a shell built-in; it doesn't exist as a stand-alone executable. (The -i options runs a "login" shell. There is also the -s option which runs a non-login shell. See below.)
If you want to specify a shell explicitly you could do so instead:
sudo -u "$SUDO_USER" /bin/sh -lc "command -v pip3"
Again, a login shell is forced, here by using the -l option.
As a safety feature, sudo normally resets the $PATH to a "safe" value before executing the shell (or the single command). That value will not have any of the modifications made in the /etc/profile and ~/.profile startup scripts, and without those modifications -- which add one or more user-specific directories to the path -- the shell will not find software such as pip3 which has been installed for individual users.

use following command by replacing $USER with the specific user name.
sudo -H -u $USER bash -c 'command -v pip3'
similarly, you can run any command as another user
syntax : sudo -H -u $USER bash -c 'INSERT_COMMAND_HERE'

Related

Executing sudo command in bash script without displaying it

I'm executing a command with sudo from bash script, and I'm wondering how to prevent sudo from displaying anything on the screen
echo "mypassword" | sudo -S cp -u /scripts/.bashrc ~/ > /dev/null 2>&1
The result will be an output displaying: [sudo] password for username:
I want to hide that output..
now, before the first comment;
This isn't the safest way, since you're entering your password into the script, but this is strictly internal servers.
Run sudo --help, we can get answer from the parameter list:
-p, --prompt=prompt use the specified password prompt
Then,
echo "mypassword" | sudo -S --prompt="" cp -u /scripts/.bashrc ~/ > /dev/null 2>&1
may do the trick.

Edit an privileged file via bash

I need to edit an privileged file using bash on Ubuntu 14.04
This simple command is not working:
sudo echo $someText >> $privilegedFile
I get this error:
Permission denied
I have no idea what is wrong with it.
Thanks.
The shell processes the redirection before it runs sudo, so $privilegedFile is still opened using the current user's permissions.
One workaround is to open the file with a program run by sudo rather than using redirections.
echo "$someText" | sudo tee -a "$privilegedFile"
Another is to start an entirely new shell with sudo and execute the full command in that shell.
sudo sh -c "echo '$someText' >> '$privilegedFile'"
You should try this:
sudo sh -c "echo $text >> $file"
do
sudo chmod u+xrw FILE
and
sudo nano FILE
Don't use echo for editing, try nano, gedit or vi.

Need to run chromium as normal user from root script

I have a kiosk that shuts down every day using rtcwake, and this uses root user. I've used && to execute the boot script after rtcwake completes, however it then starts the browser as root causing problems.
This is the command I use:
echo debian | sudo -S rtcwake -m mem -u -t $(date +%s -d '3 days 7:45') && sudo -u debian -i bash $HOME/kiosk/bin/startup.sh &.
The sudo command does work to some extent. It calls the debian user, and executes the correct script, however, it still screws up my chromium preferences.
Here is the startup script:
echo debian | sudo -S hwclock -w
export HOME=/home/debian
#log boot time
echo "Booting at" $(date) >> $HOME/kiosk/bin/logs/boot.log
#echo debian | sudo -S service connman restart
echo debian | sudo -S at 15:30 -f $HOME/kiosk/bin/shutdown.sh
crontab -u debian crontab.txt
bash $HOME/git.sh
#sudo -i -u debian
#start kiosk
export DISPLAY=:0
chromium-browser --kiosk --disable-gpu
http://localhost/kiosk/Client/main.html &
#update ip
bash /home/debian/git.sh &
I'm wondering what could be causing chrome to be executed as root. I have no idea what is going wrong.
If you execute a command with sudo it will not change environment variables like $HOME. Since per user settings are stored in $HOME, this affects the executed program if it needs such configuration files. Check this for example:
sudo -u debian bash -c 'echo $HOME'
It will print the home folder of the calling user, not the home folder of the user specified trough -u. The sudo command supports the -H command line option to handle this, however if it works depends on the security police in use.
As a solution you can use the su command instead of sudo in this case:
... && su debian -c chromium
Since su itself is executed by root you won't be asked for the password.
You must enter a password to log into a new user shell.
The command needs to be modified as follows:
echo debian | sudo -S rtcwake -m mem -u -t $(date +%s -d '3 days 7:45') && echo debian | sudo -S -u debian -i bash $HOME/kiosk/bin/startup.sh &
This avoids needing a password to log in as normal Debian user, and executes the script.

Bash script gets printed instead of being executed

This question is similar to this one: https://serverfault.com/questions/342697/prevent-sudo-apt-get-etc-from-swallowing-pasted-input-to-stdin but the answer is not satisfying (appending && to each line of bash script is not elegant) and does not explain why some users can paste/execute multiple subsequent apt-get install -y commands and others can't because stdout is swollen by the next command.
I have a script my_script.sh:
sudo apt-get install -y graphicsmagick
sudo apt-get install -y libgraphicsmagick++1-dev
...
It can have only two lines or more of sudo apt-get install stuff. The libraries (graphicsmagick, etc.) doesn't matter, it can be any library.
When I copy this script and paste it's contents to bash or just execute it like this:
cat my_script.sh | sudo -i bash
then for some reason only the first line (graphicsmagick) gets executed and the rest is just printed to the console. It happens only with sudo apt-get install -y, other scripts, which doesn't contain this command behave normally.
If I change bash to sh (which is dash) I get expected behaviour:
cat my_script.sh | sudo -i sh
Can you explain why this happens?
When answering, can you please avoid this questions/comments:
Why are you doing it this way?
Piping to your bash is not safe
Some other aspects are not safe or hackish
I just want to know why bash doesn't work as I would expect and sh does.
PS. I'm using Ubuntu 14.04, sh is dash as you can see here:
vagrant#vagrant-ubuntu-trusty-64:/tmp$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Feb 19 2014 /bin/sh -> dash
Bash and dash simply behave different when using -i flag.
Bash always goes to interactive mode even when stdin is not a terminal.
Dash on the other hand will not go into interactive mode, even with -i flag.
Probably need the -s option
If the -s option is present, or if no arguments remain after option
processing, then commands are read from the standard input. This option allows
the positional parameters to be set when invoking an interactive shell.
Bash man page
curl -s http://foo.com/bar.sh | sudo -i bash -s
Example

sudo -i doesn't work anymore with specific permissions through sudoers file

I had a bash script which called sudo -i -u user /bin/bla/whatever. That worked fine until the last update to CentOS 5.8.
That's the corresponding entry in the sudoers file:
Runas_Alias TEST = user1, user2
Defaults:test always_set_home
test ALL=(TEST) NOPASSWD: /bin/bash -c /bin/bla/whatever, /bin/bla/whatever
If I used sudo -i it seems it called the command
"/bin/bash -c /bin/bla/whatever"
(regarding the secure log). Now, since the update, it seems to call
"/bin/bash -c \/bin\/bla\/whatever"
and therefore is not allowed to. I tried to change the line in the sudoers file to
test ALL=(TEST) NOPASSWD: /bin/bash -c /bin/bla/whatever, /bin/bla/whatever, /bin/bash -c \/bin\/bla\/whatever
but thats not allowed syntax, so I tried:
test ALL=(TEST) NOPASSWD: /bin/bash -c /bin/bla/whatever, /bin/bla/whatever, /bin/bash -c \\/bin\\/bla\\/whatever
That's valid syntax but doesn't work either.
If I use sudo -H -u user /bin/bla/whatever it works fine. Even if I allow /bin/bash in the sudoers file, but that would allow anything.....
Any ideas?
Erik
Just checked the sudo man page on my fedora 16 system and it says:
-i [command]
The -i (simulate initial login) option runs the shell specified by the password database entry of the target user as a login shell. This means
that login-specific resource files such as .profile or .login will be read by the shell. If a command is specified, it is passed to the shell
for execution via the shell's -c option.
So it does not appear to be necessary to specify bash -c in your sudoers command definition.
If you call the command as sudo -i /bin/bla/whatever you should need nothing more than the following in your sudoers file:
test ALL=(TEST) NOPASSWD: /bin/bla/whatever
I can reproduce the problem on my fedora 16 system, no changes to the sudoers file I tried had any effect. I cannot find any other configuration required to make this work. All I can say is to use '-H -u ...'.
Were you running sudo -i -u user /bin/bla/whatever with arguments? From man sudoers:
A simple file name allows the user to run the command with any arguments he/she wishes. However, you may also specify command line arguments (including wildcards). Alternately, you can specify "" to indicate that the command may only be run without command line arguments.
So once you add in the /bin/bash -c you are now specifying arguments and they must match exactly.
Here's an example sudoers line:
test ALL=(ALL) NOPASSWD: /bin/bash -c /bin/true, /bin/bash -c /bin/true *, /bin/true *
With that I can do:
sudo /bin/true
sudo /bin/true foo
sudo -u /bin/true
sudo -u /bin/true foo
But not sudo true because that becomes bash -c true which does not match bash -c /bin/true.

Resources