Automate SSH and screen commands - linux

I have a PHP script with a web interface which is used to provide input into a process which I am automating. In this process, I am attempting to include using SSH and screen to run some commands (all sent through PHP's exec).
I am currently using the following which is writing echo sent from script to the screen, but isn't executing it. I've tried adding the -ne option to echo and adding \n or ^M to the end. I've also tried changing around the types of quotes I'm using, but I'm having trouble getting the code to execute (sending enter).
ssh -t -t myUser#myDomain.com 'screen -r -d -S -X myScreen stuff "echo -ne sent from script"' 2>&1
How do I go about getting that code to execute?

This took much longer to figure out than I would like to admit. They key was adding a $ before the command sent to stuff and then using a \n to send the enter press.
I added an extra screen -list; to demonstrate how to send multiple commands before entering the screen. I also added an extra echo to demonstrate how to send multiple commands to the screen.
ssh -t -t myUser#myDomain.com "screen -list; screen -r -d -X -S myScreen stuff $'echo here; echo here\n'" 2>&1

Related

Startup script to run detachted screen, switch user, and run multiple bash commands

I want to create a small startup script that does multiple things in a row in a screen.
The script starts a named, detached screen (screen -S discordbot -d -m works)
The user inside the script is changed (Neither screen -S discordbot -X "su discordbot", screen -S discordbot -X su discordbot, nor screen -S discordbot -d -m bash -c "su discordbot;" seems to work, or at least subsqeuent commands are not executed).
A cd folder change is exectuded.
A java jar or other script is started.
As I run multiple bots, the script needs to be able to do this in slight variation multiple times in a row. Any pointers on how this could be done?
The screen session that you start up will exit as soon as the process that you started exits.
This works, for instance:
$ screen -S discordbot -d -m bash
$ screen -ls
There is a screen on:
2948.discordbot (Detached)
1 Socket in <...>
As does this:
$ screen -S discordbot -d -m bin/discordbot.sh
Where bin/discordbot.sh looks like this:
#!/bin/sh
echo "Sleeping..."
sleep 10
/bin/echo -n "Hit enter to finish this script: "
read
The last two lines to prevent the screen from exiting prematurely. The other various things you want to do within that startup script should also work, assuming that you do this as root so that the su will work without prompting.

Attach to a GNU screen and then execute commands

I have seen some similar questions asked but the solutions don't seem to work in my case.
I am trying to SSH into a specific screen instance on a Node machine and then execute some commands
My current process is this:
On the remote machine I create a screen instance:
screen -dmS "my_screen"
From my local machine I do something like:
ssh <user>#<remote> -a -x -t screen -x -r my_screen -X stuff 'ruby my_script.rb'
but the output is just:
Connection at (ip) closed.
and the ruby script is not run.
If I separate the commands then the script runs correctly eg:
ssh <user>#<remote> -a -x -t screen -x -r my_screen
it connects to the screen, and then I manually enter:
ruby my_script.rb
exit
Then the script executes in the screen as intended.
What is the correct way to send commands to a screen?
In your second example, you are executing the command by typing it into the console. If that is the behavior you want to emulate, you can use the stuff command to have screen paste your text into the console to execute it.
ssh <user>#<remote> -a -x -t screen -x -r my_screen -X stuff \"ruby my_script.rb^M\"
(Note the ^M was generated using CTRL-V, CTRL-M).
This won't display anything to your open terminal, but when you reconnect to the screen, you should see the output of your command (assuming the screen was at a console window at the time you sent the command, which is the risk with this approach).
You should be using exec instead of stuff. As the name implies, exec executes commands inside the screen
ssh <user>#<remote> -a -x -t screen -x -r my_screen -X exec ruby myscript.rb

Using screen in bash script

I'm running a game server on a remote server where I use a detached screen instance to leave it running.
I'm now creating a script that can be used to shut down the server, back up all the vital files and start it up again, however I'm having a few difficulties with dealing with the screen.
I assumed that I could just switch into the detached screen in the script (after the server had already been shut down) by calling screen -r in the script.
But that doesn't seem to work because if I run the script from outside screen it just launches the server in that session.
screen -r
cd ~/servers/StarMade/
sh StarMade-dedicated-server-linux.sh
screen -d
This is what I thought would do the trick but it doesn't. Maybe somebody can help me out here. I'm not a bash expert. In fact this is propably my first bash script that doesn't include "Hello World". Thanks.
Your script, as in your example, will get executed by your sell, not the one in the screen. You need to tell the running screen to read a file and execute it - that's what the -X option is for.
Try
tempfile=$(mktemp)
cat > $tempfile <<EOF
cd ~/servers/StarMade/
sh StarMade-dedicated-server-linux.sh
EOF
screen -X readbuf $tempfile
screen -X paste .
rm -f $tempfile
You can leave screen running in a 2nd terminal session to see what happens.

How to run screen executing a command over ssh with tty

I tried many things today to have ssh start a screen session which executes a command. The goal is to run a command on a remote machine and to be able to see the output and to detach and reattach latter. I want to do it from within a script without any interaction except detaching the screen session to close. No satisfying solution so far.
ssh -t ${host} "\
source ~/.bashrc; \
echo \"done.\"; \
cd \"$exedir\"; \
if [ \$? -ne 0 ]; then \
echo \"could not cd into directory\"; \
exit 1; \
fi; \
echo \"executing remotexe.sh ...\"; \
screen -S "remotexe" -t "remotexe" -R "nice -n$prio ./remotexe.sh ${exeparams[#]}";"
Some of the problems I encounter are related to the strange ways to pass commands to screen/ssh/bash which interfere with arguments and options (I don't quite understand why they do not use -- to interpret whatever follows as commands with arguments). The above version almost works. The remaining difficulty is that commands in remotexe.sh (in particular make) obviously miss exports and definitions from .bashrc. This is why I tried to include the source ~/.bashrc. I tried to add similar commands or explicit exports to remotexe.sh but it behaves as if it was executed by /bin/sh. If I do a conventional ssh login I can immediately run the remotexe.sh script without error. I also tried adding shell -$SHELL to my .screenrc.
Where is the mistake in this solution? How can I correct it?
I haven't tested your code at all, and will not vouch for the sanity of this, but you definitely have a quoting error. Try:
ssh -t ${host} "
source ~/.bashrc;
echo done.;
cd \"$exedir\" || exit 1;
echo executing remotexe.sh ...;
screen -S remotexe -t remotexe -R nice -n$prio ./remotexe.sh ${exeparams[#]};"

How to stop a screen process in linux?

I am running a script on a remote server. I ran the script in screen, however I need to stop it before it completes since I need to update the script. I can easily detach from screen, however, is there a way to kill a screen process?
CTRL+a and then 'k' will kill a screen session.
There are a couple of 'screen' ways to kill a specific screen session from the command line (non-interactively).
1) send a 'quit' command:
screen -X -S "sessionname" quit
2) send a Ctrl-C to a screen session running a script:
screen -X -S "sessionname" stuff "^C"
In both cases, you would need to use 'screen -ls' to find the session name of the screen session you want to kill ... if there is only one screen session running, you won't need to specify the -S "sessionname" parameter.
I used this to quit hundreds of erroneous screen sessions created by a buggy command:
for s in $(screen -ls|grep -o -P "1\d+.tty"); do screen -X -S $s quit; done;
where: the grep -o -P "1\d+.tty" is the command to get session names with Perl-like name regex "1\d+.tty" which captures all sessions start with number 1, has some other numbers (\d) and end with .tty
Warning:
You should test with this command first to see you get the exact list of sessions you want before apply the above command. This is to avoid quitting unwanted sessions:
for s in $(screen -ls|grep -o -P "1\d+.tty"); do echo $s; done;
I always to this echo test whenever the list in for loop is not clear, for example, the one generated by sub-command in $() expansion.
previous answers didn't work for me on a winputty terminal and amazon ssh server connection.. but this one does work:
screen -S yourscreentitlehere -X stuff $'\003'
references:
Sending ctrl-c to specific screen session
$'\003' is ctrl+c http://donsnotes.com/tech/charsets/ascii.html
stuff is https://www.gnu.org/software/screen/manual/screen.html#Paste
I am using putty, and it seems I am already in the screen and couldn't open and close. Every time I do "exit", I just close the putty window. Here is the termimal print
>>screen -r
21063.unlimited (11/08/20 15:45:19) (Attached)
24054.cure6 (11/08/20 09:46:13) (Attached)
There is no screen to be resumed.
and
screen -S 21063.unlimited -X stuff $'\003'
does not do anything.
I found that as simple as the following line works perfect
screen -x 21063.unlimited
it sends me back into the screen and from there "exit" works.
Note that it is lower-case -x

Resources