Running each ssh command in one session - ssh

Commands the server through ssh.
The output of each command must be stored separately.
ssh -i ~/c.pem ubuntu#server 'cd /tmp'
ssh -i ~/c.pem ubuntu#server 'pwd'
I want to have "/tmp" output when I run this code.
How do I run multiple commands in previous session?

Use a ; between commands to execute them sequentially.
ssh -i ~/c.pem ubuntu#server 'cd /tmp; pwd'

Related

Remote ssh twice

I am trying to execute commands over ssh remotely.
It's 2x remote (2 level deep).
From my host, I ssh into target1 which is connected to target2.
I need the commands executed on target2.
There is no direct connection from host to target2.
Ex:
ssh root#target1 -t "ssh root#target2 -t "cat /usr/value""
The above command works.
ssh root#target1 -t "ssh root#target2 -t "echo 1 > /usr/value""
This command does not work. I get "No such file or directory"
You are trying to use a shell feature (redirection) instead of a command, so run that via shell (note: quoting gets tricky):
ssh -t root#target1 'ssh -t root#target2 /bin/bash -c \"echo 1 > /usr/value\"'
I suggest you study the man page for ssh_config. For instance, with this:
Host target2
User root
ProxyJump root#target1
your above command would be:
ssh -t target2 '/bin/bash -c "echo 1 > /usr/value"'
The next step is to use ansible (or similar) for system changes.

How to deal with "Pseudo-terminal will not be allocated because stdin is not a terminal."

ssh -t remotehost vim /tmp/x.txt
I know that I can run a command like the above.
But I would like to be able to run any local bash code in a remote machine. For this reason, I'd like to call the remote 'bash -s' so that can process any local bash code.
ssh -t remotehost 'bash -s' <<< vim /tmp/x.txt
However, the above example shows "Pseudo-terminal will not be allocated because stdin is not a terminal." Is there any way to let ssh take local bash code via stdin and run it via the remote 'bash -s'? Thanks.
ssh -t remotehost 'bash -s' <<< vim /tmp/x.txt
You're getting the "Pseudo-terminal will not be allocated..." message because you're running ssh with a single -t option, when the standard input to the ssh process isn't a TTY. ssh prints that message specifically in this case. The documentation for -t says:
-t
Force pseudo-terminal allocation. This can be used to execute arbitrary 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.
The -t command-line option is related to the ssh configuration option RequestTTY:
RequestTTY
Specifies whether to request a pseudo-tty for the session. The argument may be one of: no (never request a TTY), yes (always request a TTY when standard input is a TTY), force (always request a TTY) or auto (request a TTY when opening a login session). This option mirrors the -t and -T flags for ssh(1).
A single -t is equivalent to "RequestTTY yes", while two of them is equivalent to "RequestTTY force".
If you want your remote command(s) to run with a TTY, then specify -t twice:
ssh -tt remotehost 'bash -s' <<< vim /tmp/x.txt
or
ssh -t -t remotehost 'bash -s' <<< vim /tmp/x.txt
ssh will allocate a TTY for the remote system and it won't print that message.
If the command(s) being run on the remote system don't require a TTY, you can leave the -t option out:
ssh remotehost 'bash -s' <<< vim /tmp/x.txt
I believe the following might suit your purposes:
vim /tmp/x.txt ; ssh remotehost 'bash -s' < /tmp/x.txt
The first expression (vim ...) allows you to specify the commands you want to execute remotely as a local file called /tmp/x.txt; the second expression (ssh ...) calls the remote bash interpreter, and sends the contents of your local file to it for execution. Note that you do not need the -t option for ssh in this case (which gave rise to the pseudo-terminal warning), and that you do not need to use a here string (<<<) but can use the normal file input operator (<).
This solution seems to work for, e.g., the following file contents:
echo These commands are being executed on $HOSTNAME
echo This is a second command

how does fabric execute commands?

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.

Sudo over SSH mixes up password tty and stdin

Setup:
Local *nix machine with a SQL script script.sql (Postgres).
Remote machine remote (Debian 7) with Postgres.
I can SSH in as some_user, who is a sudoer.
Anything with Postgres needs to be done as postgres user.
The server only listens on localhost:5432.
How do I execute script.sql on remote without copying it there first?
This works well:
ssh -t some_user#remote 'sudo -u postgres psql -c "COMMANDS FOO BAR"'
The -t flag means that sudo will ask for some_user's password correctly on the local terminal.
One thing remains, to be able to pipe script.sql to psql. This does not work:
ssh -t some_user#remote 'sudo -u postgres psql' < script.sql
It fails with the message:
Pseudo-terminal will not be allocated because stdin is not a terminal.
sudo: no tty present and no askpass program specified
Edit: simplified example
Postgres and psql don't seem to figure much in the problem. The following code has the same issues:
ssh some_user#remote xargs sudo ls < input_file
The problem seems to be: we need to send 2 inputs to sudo, both the password using a tty, and the stdin to pass to ls.
Edit: even simpler
ssh localhost xargs sudo ls < input_file
sudo: no tty present and no askpass program specified
Adding -t does not work:
$ ssh -t localhost xargs sudo ls < input_file
Pseudo-terminal will not be allocated because stdin is not a terminal.
sudo: no tty present and no askpass program specified
Adding another -t does not work either:
$ ssh -t -t localhost xargs sudo ls < input_file
<content of input_file>
<waiting on a prompt>
ssh -T some_user#remote "sudo -u postgres psql -f-" < script.sql
"-f-" will read the script from STDIN. Just redirect the file in there, and there you go.
Don't bother with -t option to ssh, you don't need a full terminal for this.
ssh -T ${user}#${ip} sudo DEBIAN_FRONTEND=noninteractive postgres psql -f- < test.sql
Use DEBIAN_FRONTEND=noninteractive for resolve no tty present or equivalent of your distribution.

How to run "cd" command and keep ssh session in mosh

In ssh, I can use ssh root#myhost -t "cd mydir; bash -i" to do that, how can I run 2 commands in mosh with one line
According to man mosh(1), you can do the same with mosh, but you need to add the -t option to the ssh:
mossh root#myhost --ssh="ssh -t" "cd mydir; bash -i"