I log in to multiple Linux hosts on everyday basis using my LDAP username and then sudo su to ROOT and ORACLE user and check the database status.
As I do this everyday basis on many Linux hosts, I am curious to see whether I can run all commands in single command line?
I tried following, but it didn't help
how to execute multiple commands after sudo command
Example:
After I login using my LDAP user to Linux Host, I want to run following commands in one single command
sudo su - root -c "su - oracle; ps -ef |grep pmon; crsctl stat res -t "
After login to root, then need to switch to oracle user and then run commands
The reason your command as written doesn't work is because you don't actually run your monitoring commands as the oracle user.
The command you give to the first su invocation, su - oracle; ps -ef | grep pmon; crsctl stat res -t, attempts to do three things in sequence as root: firstly, it calls su to spawn an interactive shell as oracle; after this shell exits, it runs the ps pipeline; finally, it runs the crsctl command. Since the monitoring commands run after the second su has finished, they run as root, which isn't what you want.
The smallest change to your command that will make it work is the following:
sudo su - root -c "su - oracle -c \"ps -ef | grep pmon; crsctl stat res -t\""
(Note that you need to escape the inner pair of quotes with backslashes so that they don't end the outer quoted string.) However, you can simplify this command significantly: the first optimization you can make is to get rid of the first su call. You don't need it, because you're already root from sudo:
sudo su - oracle -c "ps -ef | grep pmon; crsctl stat res -t"
You can still make it better, though. If sudo is configured to allow you to switch to any user (not just root), you don't need to use su at all. Instead, just specify the user you want using sudo -u:
sudo -u oracle sh -c "ps -ef | grep pmon; crsctl stat res -t"
(Note that you need to add an explicit call to sh so that you can run the entire set of commands as oracle and not just the first one. sudo's documentation claims that you can use its -i or -s options for this, but they didn't work as documented in my tests.)
If you want to keep an interactive shell as the oracle user after this command, you can simply make the last command sudo runs be an interactive shell. In this case, you probably also want to pass -i to sudo so that the interactive shell has the login environment of oracle:
sudo -i -u oracle sh -c "ps -ef | grep pmon; crsctl stat res -t; $SHELL"
I am doing ssh to servers which has password less authentication from jenkins server to these servers in /tmp/san.txt by running a shell script.
jenkins#pc4mobjen01:/tmp> cat check.sh
#!/bin/bash
for i in `cat /tmp/sand.txt`
do
ssh -q mpdevops#"$i"
bash /app/home/mpdevops/sand.sh
done
jenkins#pc4mobjen01:/tmp> bash check.sh
Last login: Wed Apr 19 09:20:03 2017 from 10.4.70.42
Powered by Monsoon (Version 2.2.1519) Platform: suse 11.3
Hostname : mo-97df9aafa.dc19.saas.sap.cor Name : PC19MOBDEVOPS01
Organization : saas_prod Project : dc19_production
Url : https://monsoon.mo.sap.corp/instances/mo-97df9aafa
mo-97df9aafa[PC19MOBDEVOPS01]:~ # logout
bash: /app/home/mpdevops/sand.sh: No such file or directory
But sand.sh is present.
mo-97df9aafa[PC19MOBDEVOPS01]:~ # cat sand.sh
for j in `cat sand.txt`
do
ssh -q mpdevops#"$j"
sudo python /tmp/test.py
done
Please help.
Try entering the command to be executed on the remote client on the same line as the actual ssh command. Looks like the bash command is being executed on the local host as opposed to the client.
You should run sand.sh on the same line with ssh command:
check.sh should be:
#!/bin/bash
for i in `cat /tmp/sand.txt`
do
ssh -q mpdevops#"$i" "bash /app/home/mpdevops/sand.sh"
done
In the following script in Upstart, I'm unable to read /etc/shadow in pre-script phase, unless I use $(echo mypass | sudo -S cat /etc/shadow | grep myusername)
The script works fine if I provide my sudo pass, but I'm wondering if there is a way to do this without having to write my pass in the conf file?
node-example.conf
description "Starting Node with Upstart and Forever"
start on filesystem or runlevel [2345]
stop on runlevel [06]
expect fork
respawn
respawn limit 5 30
console output
setuid myusername
env HOME=/home/myusername
env ARGS_FILE=/etc/shadow
. /etc/shadow
script
cd $HOME
exec forever start -a -l /tmp/forever.log -o /tmp/forever.stdout.log -e /tmp/forever.stderr.log --watch --watchDirectory /home/myusername/myapp/server /home/myusername/myapp/server/server.js
end script
pre-start script
ori='myusername:$6$P...'
# cur=$(echo mypass | sudo -S cat /etc/shadow | grep myusername) -> this works
cur=$(cat $ARGS_FILE | grep myusername) -> this doesn't work
if [ "$ori" = "$cur" ]
then encfs code
else rm -rf somefile
fi
end script
There is a good reason why shadow is accessible only by root: Anybody who can change it can easily get root access. Given some time, oldish MD5 passwords can even be calculated. Bottom line: don't fiddle with /etc/shadow unless you absolutely have to. Basically, this reduces the need to changing passwords.
I am not too sure what you are trying to achieve, but doing a grep $username /etc/passwd should give you all information you need except for the hashed password.
And upstart scripts don't have to be run as root. It is perfectly fine to run a daemon as whichever user. This is achieved using the setuid stanza (there is an according setgid). So you install the service as root and let it drop privileges.
Another option would be to use a user-job. Make sure you enable user-jobs.
Whatever you do : Don't fiddle with /etc/shadow!
I have a script which copies a file, then untar and install it (agent-service) on multiple systems (IPs are read from systems.txt file). In the script, I wanted to start the agent-service as user "test". However after the script execution, when I check the target system, the agent-service is shown as running as "root" user. What could be wrong here? Am I not using su command correct within the script?
~]# ps -ef | grep agent-service
root 23511 15196 0 02:12 pts/3 00:00:00 agent-service
Script>
#!/bin/bash
export AGENT=linux-5.8.1.tar.gz
while read host; do
scp $AGENT root#$host:/opt
ssh -n root#$host 'cd /opt/linux;
tar zxvf linux-5.8.1.tar.gz;
mkdir /opt/hyperic;
useradd -m test;
chown -R test:test /opt/linux;
su - test;
/opt/linux/agent-service start'
done < systems.txt
Using su as you do here spawns a new shell that has nothing to do thus exits immediately.
Either pass the command to su:
su - test -c /opt/linux/agent-service start
Or use sudo in a similar manner:
sudo -u test /opt/linux/agent-service start
To execute a shell script in current shell, we need to use a period . or a source command. But why does it not work with a sudo permission?
I have a script with execute permission called setup.sh. When I use a period, I get this:
$ sudo . ./setup.sh
sudo: .: command not found
The source command also produces a similar error. Am I missing out something? What should I do to run the script with sudo permission in the same/current shell?
I'm not sure if this breaks any rules but
sudo bash script.sh
seems to work for me.
What you are trying to do is impossible; your current shell is running under your regular user ID (i.e. without root the access sudo would give you), and there is no way to grant it root access. What sudo does is create a new *sub*process that runs as root. The subprocess could be just a regular program (e.g. sudo cp ... runs the cp program in a root process) or it could be a root subshell, but it cannot be the current shell.
(It's actually even more impossible than that, because the sudo command itself is executed as a subprocess of the current shell -- meaning that in a sense it's already too late for it to do anything in the "current shell", because that's not where it executes.)
I think you are confused about the difference between sourcing and executing a script.
Executing a script means creating a new process, and running the program. The program can be a shell script, or any other type of program. As it is a sub process, any environmental variables changed in the program will not affect the shell.
Sourcing a script can only be used with a bash script (if you are running bash). It effectively types the commands in as if you did them. This is useful as it lets a script change environmental variables in the shell.
Running a script is simple, you just type in the path to the script. . is the current directory. So ./script.sh will execute the file script.sh in the current directory. If the command is a single file (eg script.sh), it will check all the folders in the PATH variable to find the script. Note that the current directory isn't in PATH, so you can't execute a file script.sh in the current directory by running script.sh, you need to run ./script.sh (unless the current directory is in the PATH, eg you can run ls while in the /bin dir).
Sourcing a script doesn't use the PATH, and just searches for the path. Note that source isn't a program - otherwise it wouldn't be able to change environmental variables in the current shell. It is actually a bash built in command. Search /bin and /usr/bin - you won't find a source program there. So to source a file script.sh in the current directory, you just use source script.sh.
How does sudo interact with this? Well sudo takes a program, and executes it as root. Eg sudo ./script.sh executes script.sh in a sub process but running as root.
What does sudo source ./script.sh do however? Remember source isn't a program (rather a shell builtin)? Sudo expects a program name though, so it searches for a program named source. It doesn't find one, and so fails. It isn't possible to source a file running as root, without creating a new subprocess, as you cannot change the runner of a program (in this case, bash) after it has started.
I'm not sure what you actually wanted, but hopefully this will clear it up for you.
Here is a concrete example. Make the file script.sh in your current directory with the contents:
#!/bin/bash
export NEW_VAR="hello"
whoami
echo "Some text"
Make it executable with chmod +x script.sh.
Now observe what happens with bash:
> ./script.sh
david
Some text
> echo $NEW_VAR
> sudo ./script.sh
root
Some text
> echo $NEW_VAR
> source script.sh
david
Some text
> echo $NEW_VAR
hello
> sudo source script.sh
sudo: source: command not found
Basically sudo expects, an executable (command) to follow & you are providing with a .
Hence the error.
Try this way $ sudo setup.sh
If you really want to "ExecuteCall a shell script in current shell with sudo permission" you can use exec to...
replace the shell with a given program (executing it, not as new process)
I insist on replacing "execute" with "call" because the former has a meaning that includes creating a new process and ID, where the latter is ambiguous and leaves room for creativity, of which I am full.
Consider this test case and look closely at pid 1337
# Don't worry, the content of this script is cat'ed below
$ ./test.sh -o foo -p bar
User ubuntu is running...
PID TT USER COMMAND
775 pts/1 ubuntu -bash
1408 pts/1 ubuntu \_ bash ./test.sh -o foo -p bar
1411 pts/1 ubuntu \_ ps -t /dev/pts/1 -fo pid,tty,user,args
User root is running...
PID TT USER COMMAND
775 pts/1 ubuntu -bash
1337 pts/1 root \_ sudo ./test.sh -o foo -p bar
1412 pts/1 root \_ bash ./test.sh -o foo -p bar
1415 pts/1 root \_ ps -t /dev/pts/1 -fo pid,tty,user,args
Take 'exec' out of the command and this script would get cat-ed twice. (Try it.)
#!/usr/bin/env bash
echo; echo "User $(whoami) is running..."
ps -t $(tty) -fo pid,tty,user,args
if [[ $EUID > 0 ]]; then
# exec replaces the current process effectively ending execution so no exit is needed.
exec sudo "$0" "$#"
fi
echo; echo "Take 'exec' out of the command and this script would get cat-ed twice. (Try it.)"; echo
cat $0
Here is another test using sudo -s
$ ps -fo pid,tty,user,args; ./test2.sh
PID TT USER COMMAND
10775 pts/1 ubuntu -bash
11496 pts/1 ubuntu \_ ps -fo pid,tty,user,args
User ubuntu is running...
PID TT USER COMMAND
10775 pts/1 ubuntu -bash
11497 pts/1 ubuntu \_ bash ./test2.sh
11500 pts/1 ubuntu \_ ps -fo pid,tty,user,args
User root is running...
PID TT USER COMMAND
11497 pts/1 root sudo -s
11501 pts/1 root \_ /bin/bash
11503 pts/1 root \_ ps -fo pid,tty,user,args
$ cat test2.src
echo; echo "User $(whoami) is running..."
ps -fo pid,tty,user,args
$ cat test2.sh
#!/usr/bin/env bash
source test2.src
exec sudo -s < test2.src
And a simpler test using sudo -s
$ ./exec.sh
bash's PID:25194 user ID:7809
systemd(1)───bash(23064)───bash(25194)───pstree(25196)
Finally...
bash's PID:25199 user ID:0
systemd(1)───bash(23064)───sudo(25194)───bash(25199)───pstree(25201)
$ cat exec.sh
#!/usr/bin/env bash
pid=$$
id=$(id -u)
echo "bash's PID:$pid user ID:$id"
pstree -ps $pid
# the quoted EOF is important to prevent shell expansion of the $...
exec sudo -s <<EOF
echo
echo "Finally..."
echo "bash's PID:\$\$ user ID:\$(id -u)"
pstree -ps $pid
EOF
It works without "sudo".
bash setup.sh
Even the first answer is absolutely brilliant, you probably want to only run script under sudo.
You have to specify the absolute path like:
sudo /home/user/example.sh
sudo ~/example.sh
(both are working)
THIS WONT WORK!
sudo /bin/sh example.sh
sudo example.sh
It will always return
sudo: bin/sh: command not found
sudo: example.sh: command not found
The answers here explain why it happens but I thought I'd add my simple way around the issue. First you can cat the file into a variable with sudo permissions. Then you can evaluate the variable to execute the code in the file in your current shell.
Here is an example of reading and executing an .env file (ex Docker)
sensitive_stuff=$(sudo cat ".env")
eval "${sensitive_stuff}"
echo $ADMIN_PASSWORD
Easiest method is to type:
sudo /bin/sh example.sh