How to sudo run a local script over ssh - linux

I try to sudo run a local script over ssh,
ssh $HOST < script.sh
and I tried
ssh -t $HOST "sudo -s && bash" < script.sh
Actually, I searched a lot in google, find some similar questions, however, I don't find a solution which can sudo run a local script.

Reading the error message of
$ ssh -t $HOST "sudo -s && bash" < script.sh
Pseudo-terminal will not be allocated because stdin is not a terminal.
makes it pretty clear what's going wrong here.
You can't use the ssh parameter -t (which sudo needs to ask for a password) whilst redirecting your script to bash's stdin of your remote session.
If it is acceptable for you, you could transfer the local script via scp to your remote machine and then execute the script without the need of I/O redirection:
scp script.sh $HOST:/tmp/ && ssh -t $HOST "sudo -s bash /tmp/script.sh"
Another way to fix your issue is to use sudo in non-interactive mode -n but for this you need to set NOPASSWD within the remote machine's sudoers file for the executing user. Then you can use
ssh $HOST "sudo -n -s bash" < script.sh

To make Edward Itrich's answer more scalable and geared towards frequent use, you can set up a system where you only run a one line script that can be quickly ported to any host, file or command in the following manner:
Create a script in your Scripts directory if you have one by changing the name you want the script to be (I use this format frequently to change 1 word for my script name and create the file, set permissions and open for editing):
newscript="runlocalscriptonremotehost.sh"
touch $newscript && chmod +x $newscript && nano $newscript
In nano fill out the script as follows placing the directory and name information of the script you want to run remotely in the variable lines of runlocalscriptonremotehost.sh(only need to edit lines 1-3):
HOSTtoCONTROL="sudoadmin#192.168.0.254"
PATHtoSCRIPT="/home/username/Scripts/"
SCRIPTname="scripttorunremotely.sh"
scp $PATHtoSCRIPT$SCRIPTname $HOSTtoCONTROL:/tmp/ && ssh -t $HOSTtoCONTROL "sudo -s bash /tmp/$SCRIPTname"
Then just run:
sh ./runlocalscriptonremotehost.sh
Keep runlocalscriptonremotehost.sh open in a tabbed text editor for quick updating, go ahead and create a bash alias for the script and you have yourself an app-ified version of this frequently used operation.

First of all divide your objective in 2 parts. 1) ssh to the host. 2) run the command you want as sudo. After you are certain that you can 1) access the host and 2) have sudo privileges then you can combine the two commands with &&. What x_cmd && y_cmd does is that the y_cmd gets executed after x_cmd has exited successfully.

Related

Passwordless execution of local script on remote machine as root into a local file

I've been working on a bash script that automatically runs certain scripts on remote machines and saves the logs to certain folders. As of now I have been copying the local script to the remote machine, executing it into a remote log, copying the remote log into a local folder, and then deleting the remote log and remote copy of the script.
This works, but I know it can work better if I can avoid doing all the in between steps. The one caveat is I need this to be automatic and passwordless (meaning no user input at all). One of the scripts needs to be ran as root or it won't display all the necessary information and will userlock the machine temporarily.
The code I am currently using to execute the remoteScript into a log that I later retrieve with scp is below.
sshpass -f password.txt ssh user#1.1.1.1 "echo $password | sudo -S /home/user/remoteScript.sh > remoteLog.txt"
And in my testing, execution of local script on remote machine into local log file works like below
sshpass -f password.txt ssh user#1.1.1.1 "bash -s" < /home/user/localScript.sh >> localLog.txt
How could I combine the elements of the two code examples above in order to make a local script run on a remote machine with root privilege and log the output into a local text file?
Some things I have tried that do not work include:
sshpass -f password.txt ssh user#1.1.1.1 "bash -s" < "echo $password | sudo -S /home/user/script.sh >> log.txt"
sshpass -f password.txt ssh user#1.1.1.1 "echo $password | sudo -S /home/user/script.sh" >> log.txt
and notably
sshpass -f password.txt ssh user#1.1.1.1 echo $password | sudo -S /home/user/script.sh >> log.txt
which just executes the local script with root privilege on the local machine.
I have tried many variations of the above commands and I believe its some sort of piping or flow issue but I cannot figure it out. Is there anyway to do this?
Machines are Ubuntu 16.04 and you cannot ssh in already as root.
Thanks in advance
A) It might be worth looking into an orchestration/config management solution (e.g. ansible). It's a steep learning curve at first, but initial outlay will pay off on spades down the line if you're managing multiple servers.
B) Setup password-less sudo for the scripts you want to execute, so you don't have to pass around the password in plaintext, and can run without any input. In sudoers:
user ALL=(ALL) NOPASSWD:/home/user/script.sh
C) Setup an SSH key, so you don't need to use a password at all.
But in nutshell, the code you're looking for is something like:
cat /home/user/localScript.sh | ssh user#1.1.1.1 "sudo bash" > log.txt
Which executes a non-interactive bash shell as root on the remote machine, which will take commands to execute on standard in, and the standard output will come back over the ssh channel for you to write to your local log.
Look into &> or 2>&1 if you want standard error too.

cd to directory and su to particular user on remote server in script

I have some tasks to do on a remote Ubuntu CLI-only server in our offices every 2 weeks. I usually type the commands one by one, but I am trying to find a way (write a script maybe?) to decrease the time I spend in repeating those first steps.
Here is what I do:
ssh my_username#my_local_server
# asks for my_username password
cd /path/to/particular/folder
su particular_user_on_local_server
# asks for particular_user_on_local_server password
And then I can do my tasks (run some Ruby script on Rails applications, copy/remove files, restart services, etc.)
I am trying to find a way to do this in a one-step script/command:
"ssh connect then cd to directory then su to this user"
I tried to use the following:
ssh username#server 'cd /some/path/to/folder ; su other_user'
# => does not keep my connection open to the server, just execute my `cd`
# and then tells me `su: must be run from terminal`
ssh username#server 'cd /some/path/to/folder ; bash ; su other_user'
# => keeps my connection open to the server but doesn't switch to user
# and I don't see the usual `username:~/current/folder` prefix in the CLI
Is there a way to open a terminal (keep connection) on a remote server via ssh and change directory + switch to particular in a automated way? (to make things harder, I'm using Yakuake)
You can force allocation of a pseudo-terminal with -t, change to the desired directory and then replace the shell with one where you are the desired user:
ssh -t username#server 'cd /some/path/to/folder && exec bash -c "su other_user"'
sudo -H keeps the current working directory, so you could do:
ssh -t login_user#host.com 'cd /path/to/dir/; sudo -H -u other_user bash'
The -t parameter of ssh is needed otherwise the second sudo won't be able to ask you for your password.

How to get root access after ssh in a script? [duplicate]

I have a script which runs another script via SSH on a remote server using sudo. However, when I type the password, it shows up on the terminal. (Otherwise it works fine)
ssh user#server "sudo script"
What's the proper way to do this so I can type the password for sudo over SSH without the password appearing as I type?
Another way is to use the -t switch to ssh:
ssh -t user#server "sudo script"
See man ssh:
-t Force pseudo-tty allocation. This can be used to execute arbi-
trary screen-based programs on a remote machine, which can be
very useful, e.g., when implementing menu services. Multiple -t
options force tty allocation, even if ssh has no local tty.
I was able to fully automate it with the following command:
echo pass | ssh -tt user#server "sudo script"
Advantages:
no password prompt
won't show password in remote machine bash history
Regarding security: as Kurt said, running this command will show your password on your local bash history, and it's better to save the password in a different file or save the all command in a .sh file and execute it. NOTE: The file need to have the correct permissions so that only the allowed users can access it.
Sudo over SSH passing a password, no tty required:
You can use sudo over ssh without forcing ssh to have a pseudo-tty (without the use of the ssh "-t" switch) by telling sudo not to require an interactive password and to just grab the password off stdin. You do this by using the "-S" switch on sudo. This makes sudo listen for the password on stdin, and stop listening when it sees a newline.
Example 1 - Simple Remote Command
In this example, we send a simple whoami command:
$ ssh user#server cat \| sudo --prompt="" -S -- whoami << EOF
> <remote_sudo_password>
root
We're telling sudo not to issue a prompt, and to take its input from stdin. This makes the sudo password passing completely silent so the only response you get back is the output from whoami.
This technique has the benefit of allowing you to run programs through sudo over ssh that themselves require stdin input. This is because sudo is consuming the password over the first line of stdin, then letting whatever program it runs continue to grab stdin.
Example 2 - Remote Command That Requires Its Own stdin
In the following example, the remote command "cat" is executed through sudo, and we are providing some extra lines through stdin for the remote cat to display.
$ ssh user#server cat \| sudo --prompt="" -S -- "cat" << EOF
> <remote_sudo_password>
> Extra line1
> Extra line2
> EOF
Extra line1
Extra line2
The output demonstrates that the <remote_sudo_password> line is being consumed by sudo, and that the remotely executed cat is then displaying the extra lines.
An example of where this would be beneficial is if you want to use ssh to pass a password to a privileged command without using the command line. Say, if you want to mount a remote encrypted container over ssh.
Example 3 - Mounting a Remote VeraCrypt Container
In this example script, we are remotely mounting a VeraCrypt container through sudo without any extra prompting text:
#!/bin/sh
ssh user#server cat \| sudo --prompt="" -S -- "veracrypt --non-interactive --stdin --keyfiles=/path/to/test.key /path/to/test.img /mnt/mountpoint" << EOF
SudoPassword
VeraCryptContainerPassword
EOF
It should be noted that in all the command-line examples above (everything except the script) the << EOF construct on the command line will cause the everything typed, including the password, to be recorded in the local machine's .bash_history. It is therefore highly recommended that for real-world use you either use do it entirely through a script, like the veracrypt example above, or, if on the command line then put the password in a file and redirect that file through ssh.
Example 1a - Example 1 Without Local Command-Line Password
The first example would thus become:
$ cat text_file_with_sudo_password | ssh user#server cat \| sudo --prompt="" -S -- whoami
root
Example 2a - Example 2 Without Local Command-Line Password
and the second example would become:
$ cat text_file_with_sudo_password - << EOF | ssh va1der.net cat \| sudo --prompt="" -S -- cat
> Extra line1
> Extra line2
> EOF
Extra line1
Extra line2
Putting the password in a separate file is unnecessary if you are putting the whole thing in a script, since the contents of scripts do not end up in your history. It still may be useful, though, in case you want to allow users who should not see the password to execute the script.
Assuming you want no password prompt:
ssh $HOST 'echo $PASSWORD | sudo -S $COMMMAND'
Example
ssh me#localhost 'echo secret | sudo -S echo hi' # outputs 'hi'
The best way is ssh -t user#server "sudo <scriptname>", for example ssh -t user#server "sudo reboot".
It will prompt for password for user first and then root(since we are running the script or command with root privilege.
I hope it helped and cleared your doubt.
NOPASS in the configuration on your target machine is the solution. Continue reading at http://maestric.com/doc/unix/ubuntu_sudo_without_password
echo $VAR_REMOTEROOTPASS | ssh -tt -i $PATH_TO_KEY/id_mykey $VAR_REMOTEUSER#$varRemoteHost
echo \"$varCommand\" | sudo bash
confirming that the answer of #ofirule is working like a charm.
I try ot even with sshpass & it works. This is how to use it with sshpass:
echo $pass | sshpass -p $pass ssh -tt cloud_user#$ip "sudo su -"
you will find yourself in the root shell directly

How to do ssh in a bash script with lot of commands?

I tried to run the following command in a bash script but only till ./install.sh rereplica is called . Rest of the commands are not called at all.
ssh $node2user#$node2 "cd /tmp; tar -xf $mmCS.tar; cd $mmCS; ./install.sh csreplica; ./install.sh keepalived $vip low;./install.sh haproxy $node1:8080 $node2:8080 $vip:8080; ./install.sh confmongo $dbPath"
You can give ssh a script on standard input:
ssh $node2user#$node2 < my_script.sh
If I have to do execute a complex script using SSH, I usually write a script locally, copy it on the target machine with SSH and then execute it there:
scp foo.sh $node2user#$node2:
ssh $node2user#$node2 "bash ./foo.sh"
That way, I can debug the script simply by invoking it with bash -x and I can use the full power of BASH.
Alternatively, you can use
ssh $node2user#$node2 "set +x; cd /tmp; ..."

shell scripting that uses sudo su - team and perform rest command under this sudo access only

#!/bin/bash
sudo su - team //// this will change user to team
<somecommnand>
here i have some command like sqlplus that run under this privilege only .
but ,this script first asked for password then i give password but it not run rest of command like .
How to write script that use sudo su and run all command in script below it.
You have several options.
You can just move the sudo command outside of your script, and have people call it like this:
sudo -u team /path/to/your/script
You can put the sudo command in one script and the actual commands you want to run with elevated privileges in another script. That is, people run your_script, which looks like:
#!/bin/sh
sudo -u team /path/to/your_script.real
And your_script.real contains the commands that you want to run with elevated privileges.
If you really want everything in the same script and you don't mind being a little too clever, you can have the script check re-execute itself using sudo like this:
#!/bin/sh
TEAM_UID=500 # replace with correct uid
if [ "$UID" != $TEAM_UID ]; then
exec sudo -u team $0
fi
And you can also feed commands to a shell from stdin, like this:
#!/bin/sh
sudo su - team <<'EOF'
echo my uid is $UID
EOF
You could try having all of the commands on the same line and seperate them with ';'.
eg. 'sudo su; somecommand; another command'
Could also run that script as the intended user.

Resources