Shell script and sudo - unix

In my shell script i have the following line:
export PATH=$PATH:/home/$USER/somedir
Say im logged in as user mike. I need to execute the shell script as root, so i run it as sudo filename.sh, so $USER becomes root in my path in that case.
I want it to be that of the user running the script, i.e. mike instead of root. Is there a way to achieve this?
Thank You

Do you have to use /home/$USER, or will $HOME do the trick? IIRC, sudo doesn't override the value of $HOME.

Use $SUDO_USER (if you insist on using $USER directly, set its value as shown):
$ cat script.sh
#!/bin/bash
if [ "$SUDO_USER" != "" ]; then
USER=$SUDO_USER;
fi
export PATH=$PATH:/home/$USER/somedir
Or cheat using $USER as the first parameter to the script (error checking is an exercise for the reader):
$ cat script.sh
#!/bin/bash
USER=$1
export PATH=$PATH:/home/$USER/somedir
Then:
$ sudo ./script.sh $USER
Or use $HOME, as suggested by Chris Jester-Young. You could use bash to remove the "/home/" prefix, but that would be an ugly hack.

If you're willing to use su instead of sudo, you can do
su -cp filename.sh
to execute the command while preserving your environment.

You can try using $UID, which should still be set to the user's real ID number and retrieving their name out of the password database based on that.

If you need to preserve environnement, you can use the -E option of sudo. But it needs some configuration and security politics ... That applies if the $HOME solution proposed by Chris JY does not apply as it is simpler.
my 2 cents

sudo is different form "root" user. If any user has sudo privileges, that means he has the admin rights that are available with the user "root". That is, using sudo doesn't change the user to root.

Related

User cannot execute a command when I already specified it in /etc/sudoers

Hello I want to run the following command as a user called arago:
`echo 1SgOSWjT | passwd --stdin JohnDoe`
This is to change the password for the user John Doe. However I get the following message:
Only root can do that.
I modified the /etc/sudoers file as follows:
`User_Alias ADMINS = arago`
`Cmnd_Alias LOCATE = /usr/bin/passwd`
`ADMINS ALL = NOPASSWD: LOCATE `
Why can I not still run the passwd command?
You probably need
echo 1SgOSWjT | sudo passwd --stdin JohnDoe
but it is a very bad habit that you are taking.
BTW, you might install the super package or the ninja package and use it instead of sudo
I believe however that your entire approach is a security risk.

Switch user as well as environment variable in Unix Shell Script

I'm currently working on a script that logs into another user account using
su username -c "comand1; comand2"
There's no sudo command in the shell.
However the environment variables do not change.
For example, the work directories are different with different users. So when the user is switched in the script, I expect that the $HOME variable should contain different work directories.
Does anyone know how to solve this problem?
You are probably looking for the -l (or just -) option to make it a login shell. See the manual for su(1).
One hack-ish kind of way would be put all env variables of the second user in a file (like .bashrc) and source it first in the list of the commands:
su username -c "source file_name; comand1; comand2"
There are two issues:
First: If you user " to delimit the argument for -c then everything in this argument is expanded by the calling shell and not by the executed shell. You can use ' instead of " to prevent this.
Second: By default su does not perform the same steps as during a real user login. Use the -l or - options. This may be required in your case or not - just try it.
Together:
> echo $HOME
/root
> su -c "echo $HOME" user -l
/root
> su -c 'echo $HOME' user -l
/home/user
> su -c 'echo $HOME' user
/home/user

How to write a shell script that runs some commands as superuser and some commands not as superuser, without having to babysit it?

I want to write a shell script to automate a series of commands. The problem is some commands MUST be run as superuser and some commands MUST NOT be run as superuser. What I have done so far is something like this:
#!/bin/bash
command1
sudo command2
command3
sudo command4
The problem is, this means somebody has to wait until command1 finishes before they are prompted for a password, then, if command3 takes long enough, they will then have to wait for command3 to finish. It would be nice if the person could get up and walk away, then come back an hour later and be done. For example, the following script has this problem:
#!/bin/bash
sleep 310
sudo echo "Hi, I'm root"
sleep 310
sudo echo "I'm still root?"
How can I make it so that the user can just enter their password once, at the very start, and then walk away?
Update:
Thanks for the responses. I'm running on Mac OS X Lion and ran Stephen P's script and got different results: (I also added $HOME)
pair#abbey scratch$ ./test2.sh
uid is 501
user is pair
username is
home directory is /Users/pair
pair#abbey scratch$ sudo ./test2.sh
Password:
uid is 0
user is root
username is root
home directory is /Users/pair
File sutest
#!/bin/bash
echo "uid is ${UID}"
echo "user is ${USER}"
echo "username is ${USERNAME}"
run it: `./sutest' gives me
uid is 500
user is stephenp
username is stephenp
but using sudo: sudo ./sutest gives
uid is 0
user is root
username is stephenp
So you retain the original user name in $USERNAME when running as sudo. This leads to a solution similar to what others posted:
#!/bin/bash
sudo -u ${USERNAME} normal_command_1
root_command_1
root_command_2
sudo -u ${USERNAME} normal_command_2
# etc.
Just sudo to invoke your script in the first place, it will prompt for the password once.
I originally wrote this answer on Linux, which does have some differences with OS X
OS X (I'm testing this on Mountain Lion 10.8.3) has an environment variable SUDO_USER when you're running sudo, which can be used in place of USERNAME above, or to be more cross-platform the script could check to see if SUDO_USER is set and use it if so, or use USERNAME if that's set.
Changing the original script for OS X, it becomes...
#!/bin/bash
sudo -u ${SUDO_USER} normal_command_1
root_command_1
root_command_2
sudo -u ${SUDO_USER} normal_command_2
# etc.
A first stab at making it cross-platform could be...
#!/bin/bash
#
# set "THE_USER" to SUDO_USER if that's set,
# else set it to USERNAME if THAT is set,
# else set it to the string "unknown"
# should probably then test to see if it's "unknown"
#
THE_USER=${SUDO_USER:-${USERNAME:-unknown}}
sudo -u ${THE_USER} normal_command_1
root_command_1
root_command_2
sudo -u ${THE_USER} normal_command_2
# etc.
You should run your entire script as superuser. If you want to run some command as non-superuser, use "-u" option of sudo:
#!/bin/bash
sudo -u username command1
command2
sudo -u username command3
command4
When running as root, sudo doesn't ask for a password.
If you use this, check man sudo too:
#!/bin/bash
sudo echo "Hi, I'm root"
sudo -u nobody echo "I'm nobody"
sudo -u 1000 touch /test_user
Well, you have some options.
You could configure sudo to not prompt for a password. This is not recommended, due to the security risks.
You could write an expect script to read the password and supply it to sudo when required, but that's clunky and fragile.
I would recommend designing the script to run as root and drop its privileges whenever they're not needed. Simply have it sudo -u someotheruser command for the commands that don't require root.
(If they have to run specifically as the user invoking the script, then you could have the script save the uid and invoke a second script via sudo with the id as an argument, so it knows who to su to..)

How to sudo as a different user inside a script?

I have a wrapper script which calls two scripts aaa.sh and bbb.sh. These two scripts should be executed as different users as
sudo -H -u user1
. /user/bin/scripts/aaa.sh
sudo -H -u user1
. /user/bin/scripts/bbb.sh
but the sudo command can't be executed inside a script. Need help...
If you just want to switch users, you should use 'su' not sudo, right?
su user1 -c ./user/bin/scripts/aaa.sh
(that is unless you actually do need elevated privileges)
sudo can be used inside a script, but is the user that executes this script actually allowed to use sudo? Check your /etc/sudoers file.
sudo can be used only if the user name is mapped in /etc/sudoers file as mentioned above. But he may not have the complete priveleges as compared to su user.

Post to Twitter using Terminal with CURL

I got this far:
:~ curl -u username:password -d status="new_status" http://twitter.com/statuses/update.xml
Now, how can I alias this with variables so I can easily twit from Terminal? How can I make the alias working through different sessions (when I close Terminal aliases reset).
Thanks!
Basic Authentication is no longer supported by twitter. Please use OAuth.
You clearly have the alias command: stick it in your ~/.bashrc and it will be set up when your bash shell starts. (.shrc should also work for sh-like shells.)
If you stick it in a script file as the previous answer suggests:
(a) add the line
#!/bin/sh
at the top;
(b) make sure it's on your path or you'll have to type the whole path to the script when you want to run it.
(c) to make it executable,
chmod +x tweet.sh
what about putting it a file and using argument 1 as $1:
# tweet.sh "post my status, moron!":
curl -u username:password -d status="$1" http://twitter.com/statuses/update.xml
will that work?
You need to create a file in your home directory that will get referenced each time a new terminal opens.
Do a bit of research as to what to name the file, according to what type of shell you are using (tcsh looks for a file called .tcshrc while bash looks for .bashrc).
Once you have that file, make it executable by running:
chmod +x name_of_file
Then, in that file, create your alias (again, you'll need to research how to do this depending on what type of shell you are using). For tcsh, my alias looks like this:
alias tw 'curl -u username:password -d status=\!^ http://twitter.com/statuses/update.xml'
Bash aliases use an equals sign. A bash alias would look something more like this:
alias tw='curl -u username:password -d status=\!^ http://twitter.com/statuses/update.xml'
Note the change in the command after "status=". The \!^ tells the line of code to insert the first argument passed after the alias itself.
Save your file.
You could then run an update to twitter by typing the following in a new terminal:
tw 'my first post to twitter via the terminal, using aliases'
Don't forget to escape 'special' characters (like exclamations) with the escape character, \ (i.e. \!)
Since Basic Authentication is no longer supported by twitter, you have to use OAuth to achieve your goal.
But if you just want to post to Twitter using terminal, there are many application can do it.
Take a look at Rainbowstream or t
With rainbowstream, the following lines will let you tweet from console:
$ sudo pip install rainbowstream
$ rainbowstream
[#yourscreenname]t whatever you want

Resources