I'm wondering why executing su in an ssh command does not appear to be having the desired effect of switching users before executing the subsequent commands, as illustrated below:
The following command:
bob#server1:~$ sudo ssh -n root#server2 "su bob; env"
Produces the following output:
...
USER=root
PWD=/root
HOME=/root
LOGNAME=root
...
I expected the output to reflect that which user bob would have observed, however it is the environment of the root user. I have found, however, that the following command achieves the desired effect:
bob#server1:~$ sudo ssh -n root#server2 "su bob -c \"env\""
This command produces the following output:
...
USER=bob
PWD=/root
HOME=/users/bob
LOGNAME=bob
...
I would like to understand why the first way (executing "su bob; env") does not work.
Consider first what the su command does: it starts a new shell as the target user. Ignoring ssh for a moment, just become root on your local system and try running something like this:
su someuser; env
What happens? You will get a shell as someuser, and when you exit that shell, the env command executes in root's environment. If you wanted to run the env command as someuser, you would need:
su someuser -c env
This instructs su to run the env command as someuser.
When you run:
sudo ssh -n root#server2 "su bob; env"
The shell spawned by su exits immediately, because you've disabled stdin (with -n), and the env command executes in root's environment, just like in this example.
Related
I have gitlab CI job which had a script execution like below:
stage: permissions
script:
sshpass -p "${PASSWORD}" ssh ${USER}#${HOST} sudo chown -cv user_a:user_a ${directory}/test.txt
The above gives me following error:
sudo: sorry, you must have a tty to run sudo
If i add -t with ssh i get:
Pseudo-terminal will not be allocated because stdin is not a terminal.
sudo: sorry, you must have a tty to run sudo
If i add -tt with ssh, the job keeps waiting for me to enter the password.
My requirement is to execute a remote command using ssh and text password i.e. sshpass, is there a way i can achieve this without change any sudoers permissions over the server?
Use somethinc like:
sshpass -p "${PASSWORD}" ssh ${USER}#${HOST} sh -c "echo ${PASSWORD} | sudo chown -cv user_a:user_a ${directory}/test.txt"
Example for write password from not tty to sudo:
echo ${PASSWORD} | sudo -S command
p.s. For configure servers use Ansible, he handles such tasks very easily.
I'm using password-less key based login with sudo to execute remote commands. I have figured out that I have to spawn a new shell to execute commands that write to root areas of the remote file system. But, I would like a clear explanation of exactly why this is the case?
This fails:
sudo -u joe ssh example.com "sudo echo test > /root/echo_test"
with:
bash: /root/echo_test: Permission denied
This works fine:
sudo -u joe ssh example.com "sudo bash -c 'echo test > /root/echo_test'"
It's the same reason that a local sudo echo test >/root/echo_test will fail (if you are not root) -- the redirection is done by the shell (not the sudo or echo command) which is running as the normal user. sudo only runs the echo command as root.
With sudo -u joe ssh example.com "sudo echo test > /root/echo_test", the remote shell is running as a normal user (probably joe) and does not have permission to write to the file. Using an extra bash invokation works, because sudo then runs bash as root (rather than echo), and that bash can open the file and do the redirect.
i am wondering how does fabric execute commands.
Let's say I give him env.user=User, env.host=HOST. Then i ask him to sudo('ls')
Is that equivalent to me typing in a shell : ssh User#host 'sudo(/bin/ls)'
or it's more : ssh User#host in a first time, then sudo ls commande in a seconde time ?
I'm asking that because sometimes using a shell, if the TTY has a bad configuration (I am a bit blurry on this), ssh User#Host 'sudo /bin/ls'
return : sudo: no tty present and no askpass program specified
but you can first log in with ssh User#Host then sudo ls and it works.
I don't know how to replicate the no tty error, but I know it can occurs. Would this block the sudo commande from Fabric?
Basically how it works is:
First a connection is established (equivalent as doing ssh User#host)
Over this connection a command is executed as follows:
sudo -S -p 'sudo password:' /bin/bash -l -c "your_command"
You can also allow Fabric not to request a pty with either pty=False argument, env.always_use_pty=False or --no-pty commandline option.
I'm trying to login to a ssh server and to execute something like:
ssh user#domain.com 'sudo echo "foobar"'
Unfortunately I'm getting an error:
sudo: no tty present and no askpass program specified
Google told me to either set the environment variable SSH_ASKPASS or to set askpass in the sudoers file. My remote machine is running on Debian 6 and I've installed the packages ssh-askpass and ssh-askpass-gnome and my sudoers file looks like this:
Defaults env_reset
Defaults askpass=/usr/bin/ssh-askpass
# User privilege specification
root ALL=(ALL) ALL
user ALL=(ALL) ALL
Can someone tell what I'm doing wrong and how to do it better.
There are two ways to get rid of this error message. The easy way is to provide a pseudo terminal for the remote sudo process. You can do this with the option -t:
ssh -t user#domain.com 'sudo echo "foobar"'
Rather than allocating a TTY, or setting a password that can be seen in the command line, do something like this.
Create a shell file that echo's out your password like:
#!/bin/bash
echo "mypassword"
then copy that to the node you want using scp like this:
scp SudoPass.sh somesystem:~/bin
Then when you ssh do the following:
ssh somesystem "export SUDO_ASKPASS=~/bin/SudoPass.sh;sudo -A command -parameter"
Another way is to run sudo -S in order to "Write the prompt to the standard error and read the password from the standard input instead of using the terminal device" (according to man) together with cat:
cat | ssh user#domain.com 'sudo -S echo "foobar"'
Just input the password when being prompted to.
One advantage is that you can redirect the output of the remote command to a file without "[sudo] password for …" in it:
cat | ssh user#domain.com 'sudo -S tar c --one-file-system /' > backup.tar
Defaults askpass=/usr/bin/ssh-askpass
ssh-askpass requires X server, so instead of providing a terminal (via -t, as suggested by nosid), you may forward X connection via -X:
ssh -X user#domain.com 'sudo echo "foobar"'
However, according to current documentation, askpass is set in sudo.conf as Path, not in sudoers.
How about adding this in the sudoers file:
user ALL=(ALL) NOPASSWD: ALL
I run
ssh root#myhost "sh -x" < myremotecommands.sh
where myremotecommands.sh contains:
#!/bin/sh
sudo su
apt-get update
sudo su -l -p jenkins
whoami
however the command whoami returns 'root'.
I need to be user jenkins to perform some installations.
How can I switch to the user jenkins in the middle of the script ?
You just have to use "su" command with "-s /bin/bash" argument. It´s needed because jenkins user was not supposed to be used interactively, so it doesn´t have the bash defined.
su jenkins -s /bin/bash
After this, the "whoami" command will report you as "jenkins" user.
Use $USER. That will give you the username you logged in as. Whoami returns the user you're currently operating as.
Problem solved:
#!/bin/sh
sudo su
apt-get update
su jenkins <<HERE
whoami
echo usr=$USER
HERE
will output:
jenkins
usr=root
Source:
http://www.daniweb.com/software-development/shell-scripting/threads/14498