shell script to run multiple scripts from different shells - shell

I want to run 2 different scripts from a single master shell script.
The first one uses the following command "rosh -n -l abcd" (It will log me in to the server with the user abcd and on the same shell I need to run the other script#2 and script#3 ...etc.)
Script#2- From there I need to change user using su - xyz and provide a password (it is fine if I can hardcode this in the file) (Script name is logintoServer)
Script#3- Run some script in the same shell to verify start of stop of server...
I have done the following but failed
I have one script which has rosh -n <servername> -l abcd /bin/sh -c "su - xyz" (I have to run this command in the same shell)
The below are the errors:
I am getting error while executing "standard in must be a tty"
I have tried to create 2 different scripts and run, but the problem is once the first script is run it does not run the 2nd script till I exit the script. (I need to run the 2nd script from the sub-shell created by the 1st script....)

I don't have rosh and I don't have a man page for rosh but a similar problem exists with ssh:
ssh localhost /bin/bash -c 'echo x' # (prints nothing)
ssh localhost "/bin/bash -c 'echo x'" # x
ssh localhost "/bin/bash -c 'tty'" # not a tty
ssh -t localhost "/bin/bash -c 'tty'" # /dev/pts/12\nConnection to localhost closed.
ssh localhost "/bin/bash -c 'su - $USER'" # su: must be run from a terminal
ssh -t localhost "/bin/bash -c 'su - $USER'"
the last asked for a password and then gave me a shell, so that would be 2 of 3 steps.
so one idea is to see if rosh has the -t option, too and the other is to enclose /bin/bash... with quotes, too (will require some escaping for the 3rd level).
What does rosh say with equivalent commands?
UPDATE
latest state:
rosh -n $host -l abcd -t "/bin/sh -c 'su - $user'"
Next I would save one step by saying /bin/su - xyz instead /bin/sh -c 'su - xyz', then you can use single quotes later, e.g.
rosh -n $host -l abcd -t "/bin/su - $user -c 'echo $PATH'"
this should print $PATH as seen by the echo command. Apparently it doesn't contain java. try man su, which java, man which.
su ... -c cmd runs cmd with the shell specified in /etc/passwd, so say </etc/passwd grep $user on the remote machine to find out which shell is used. if it's bash you can change $PATH in .bashrc or so, for other shells I don't know exactly.
Or specify an absolute path when launching java.
regarding password: with ssh I managed to use private key / public key and ssh-agent. For rosh I don't know if that works, too.

Related

Running "sudo su" within a gitlab pipeline

I've installed some software on a server that my gitlab runner SSH's to, and one of the commands needs to be run after doing sudo su. If I run it as a regular user, but with sudo in front of it - it doesn't work. I have to first completely switch to the sudo user first.
This works fine when I SSH into the server and do the commands manually. But when I try it from the pipeline (rough code below):
my_script:
stage: stage
script:
- ssh -o -i id_rsa -tt user#1.1.1.1 << EOF
- sudo su
- run_special_command <blah blah>
- exit
# above exits from the SSH. below should stop the pipeline
- exit 0
- EOF
I get very weird output like the below:
$ sudo su
[user#1.1.1.1 user]$ sudo su
echo $'\x1b[32;1m$ run_special_command <blah blah>\x1b[0;m'
run_special_command <blah blah>
echo $'\x1b[32;1m$ exit\x1b[0;m'
exit
echo $'\x1b[32;1m$ exit 0\x1b[0;m'
exit 0
echo $'\x1b[32;1m$ EOF\x1b[0;m'
And what I'm seeing is that it doesn't even run the command at all - and I can't figure out why.
In this case, you need to put your script as a multi-line string in your YAML. Alternatively, commit a shell script to repo and execute that.
and one of the commands needs to be run after doing sudo su. If I run it as a regular user, but with sudo in front of it - it doesn't work.
As a side note, you can probably use sudo -E instead of sudo su before the command. But what you have should also work with the multi-line script.
MyJob:
script: |
ssh -o -i id_rsa -tt user#host << EOF
sudo -E my_command
EOF
exit 0
Alternatively, write your script into a shell script committed to the repository (with executable permissions set) and run it from your job:
MyJob:
script: “my_script.sh”

How to sudo su; then run command

Can anyone help me to to solve following issue
i need to ssh to another server by e.g. ubuntu user which has permission to run sudo su fore sure then execute pm2 restart command
full command look like this
#!/bin/sh
CMD="sudo su; pm2 restart 0; pm2 restart 1; exit;"
ssh -i somepemfile.pem ubuntu#1.1.1.1 $CMD
for example i can run normally any command with sudo
CMD="sudo /etc/init.d/apache2 restart"
but with sudo su case it somehow hang and do not response
Unless you have an unusual setup, you can't normally string su with other preceding commands like that. I would imagine it is running sudo su, then hanging in the root environment/session, because it's waiting for you to exit before preceding to the pm2 commands. Instead, I would consider something along the lines of this using the -c option:
CMD="sudo su -c 'pm2 restart 0; pm2 restart 1'"
ssh -i somepemfile.pem ubuntu#1.1.1.1 "$CMD"
As suggested in another answer, it would also probably be useful to encapsulate the $CMD variable in quotes in the ssh call.
su normally puts you in a sub shell which you can see by echoing the current PID (process id)
$ echo $$
94260
$ sudo echo $$
94260
$ sudo su
$ echo $$
94271
But to get around this you can pipe the commands you want to run to su like this
$ echo "whoami" | sudo su
root
And we run multiple commands
$ echo "uptime;whoami" | sudo su
11:29 up 8 days, 19:20, 4 users, load averages: 4.55 2.96 2.65
root
Now to make this work with ssh
$ ssh wderezin#localhost 'echo "uptime;whoami" | sudo su'
sudo: no tty present and no askpass program specified
Darn it, we need allocate a tty for the su command. Add the -t option which allocates a TTY during the remote execution.
$ ssh -t wderezin#localhost 'echo "uptime;whoami" | sudo su'
11:36 up 8 days, 19:26, 5 users, load averages: 2.97 2.97 2.76
root
Your command would look this
ssh -i somepemfile.pem ubuntu#1.1.1.1 'echo "pm2 restart 0; pm2 restart1" | sudo su'
Use -c option of su to specify the command
From man su
In particular, an argument of -c will cause the next argument to be treated as a command by most command interpreters. The command will be executed by the shell specified in
/etc/passwd for the target user.
CMD="sudo su -c \"pm2 restart 0; pm2 restart 1;\""
You need to quote the expansion so that the entire string is parsed on the remote end.
ssh -i somepemfile.pem ubuntu#1.1.1.1 "$CMD"
Otherwise, the expansion is subject to word splitting, and the remote shell gets a string which consists of the command sudo and the arguments su;, restart, 0;, pm2, restart;, 1;, and exit;. That is, ssh will escape the semicolons when it builds a single string from the separate arguments you pass.
However, that doesn't solve the problem of running pm2 in the shell started by sudo. That is addressed by ramki.

How to copy echo 'x' to file during an ssh connection

I have a script which starts an ssh-connection.
so the variable $ssh start the ssh connection.
so $SSH hostname gives the hostname of the host where I ssh to.
Now I try to echo something and copy the output of the echo to a file.
SSH="ssh -tt -i key.pem user#ec2-instance"
When I perform a manual ssh to the host and perform:
sudo sh -c "echo 'DEVS=/dev/xvdbb' >> /etc/sysconfig/docker-storage-setup"
it works.
But when I perform
${SSH} sudo sh -c "echo 'DEVS=/dev/xvdb' > /etc/sysconfig/docker-storage-setup"
it does not seem to work.
EDIT:
Also using tee is working fine after performing an ssh manually but does not seem to work after the ssh in the script.sh
The echo command after an ssh of the script is happening on my real host (from where I'm running the script, not the host where I'm performing an ssh to). So the file on my real host is being changed and not the file on my host where I've performed an ssh to.
The command passed to ssh will be executed by the remote shell, so you need to add one level of quoting:
${SSH} "sudo sh -c \"echo 'DEVS=/dev/xvdb' > /etc/sysconfig/docker-storage-setup\""
The only thing you really need on the server is the writing though, so if you don't have password prompts and such you can get rid of some of this nesting:
echo 'DEVS=/dev/xvdb' | $SSH 'sudo tee /etc/sysconfig/docker-storage-setup'

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.

How can I execute a script from my local machine in a specific (but variable) directory on a remote host?

From a previous question, I have found that it is possible to run a local script on a remote host using:
ssh -T remotehost < localscript.sh
Now, I need to allow others to specify the directory in which the script will be run on the remote host.
I have tried commands such as
ssh -T remotehost "cd /path/to/dir" < localscript.sh
ssh -T remotehost:/path/to/dir < localscript.sh
and I have even tried adding DIR=$1; cd $DIR to the script and using
ssh -T remotehost < localscript.sh "/path/to/dir/"
alas, none of these work. How am I supposed to do this?
echo 'cd /path/to/dir' | cat - localscript.sh | ssh -T remotehost
Note that if you're doing this for anything complex, it is very, very important that you think carefully about how you will handle errors in the remote system. It is very easy to write code that works just fine as long as the stars align. What is much harder - and often very necessary - is to write code that will provide useful debugging messages if stuff breaks for any reason.
Also you may want to look at the venerable tool http://en.wikipedia.org/wiki/Expect. It is often used for scripting things on remote machines. (And yes, error handling is a long term maintenance issue with it.)
Two more ways to change directory on the remote host (variably):
echo '#!/bin/bash
cd "$1" || exit 1
pwd -P
shift
printf "%s\n" "$#" | cat -n
exit
' > localscript.sh
ssh localhost 'bash -s "$#"' <localscript.sh '/tmp' 2 3 4 5
ssh localhost 'source /dev/stdin "$#"' <localscript.sh '/tmp' 2 3 4 5
# make sure it's the bash shell to source & execute the commands
#ssh -T localhost 'bash -c '\''source /dev/stdin "$#"'\''' _ <localscript.sh '/tmp' 2 3 4 5

Resources