linux can't access screens on crontab - linux

I have created a bash file that executes a python script on an existing screen called 'cronscreen'. The bash file contains the following line:
screen -S cronscreen -X stuff "python test.py$(printf \\r)"
When I run the file from the command line, it works fine, and I see the output is printed when I attach my 'cronscreen'. However, I would like it to run in cron, so I have set up crontab as follows:
* * * * * myuser /home/myuser/myscript.sh > /home/ec2-user/agg.log
The cron is executed because I can see that the file agg.log is regenerated every minute, but when I attach 'cronscreen', I see no output printed there (and agg.log is empty). Why is that? Thanks.
Update:
I also tried changing the script to this(re-attaching the screen), but no change:
screen -r cronscreen
screen -S cronscreen -X stuff "python test.py$(printf \\r)"

screen needs an tty active to create a session which is not what is available under cron.
You need to split this into two parts , the first is to run screen and make it detach - screen -dmS cronscreen and then in your cronjob attach to the screen session with -r cronscreen

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.

bash script to auto run on boot, make screen, execute a command and detach

I am using Centos 7 and on boot I would like to:
Make a screen
Execute a command: osrm-routed --algorithm=MLD
~/osrm-backend/profiles/australia-latest.osrm
Detatch from screen (possibly not needed, just as long as I can
access it myself after its running in future)
Here is something I have thought about, although not correct and wont work
filename: mapstart.sh
Contents of file:
#!/bin/bash
/usr/bin/screen -dmS mapapi osrm-routed --algorithm=MLD ~/osrm-backend/profiles/australia-latest.osrm
With your help with the script. I am not sure the best way to run that on boot with centos 7.
Appreciate your help and input.
For those who would like to know. The issue was with OSRM and centos. I was able to get it running using the full paths of everything and the following in crontab -e
To get the full path of osrm-backend i ran the command of:
which osrm-routed
It returned the result of:
/usr/local/bin/osrm-routed
That then enabled me to add the full path of the command I was trying to run from crontab -e which is required. From there it worked running the below in crontab -e
#reboot /usr/bin/screen -dm -S pistartup /usr/local/bin/osrm-routed --algorithm=MLD ~/osrm-backend/profiles/australia-latest.osrm
break down of all the above:
runs command at reboot only:
#reboot
full path to screen command:
/usr/bin/screen
create screen with name of pistartup and detach:
-dm -S pistartup
my particular command i wanted to run inside the screen:
/usr/local/bin/osrm-routed --algorithm=MLD ~/osrm-backend/profiles/australia-latest.osrm
Now when ever the machine is rebooted. it has created a screen and run my command. To resume the screen manually If i ever wanted to, i could issue the command of:
screen -r pistartup

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

Run commands in screen after creating one per bash

I have the following bash file which should create a screen, go to a directory and then start a node script:
screen -S shared // 1
cd /home/nodejsapp // 2
node start.js app.js // 3
The problem is, after executing 1, I indeed see the screen 'shared', but 2 & 3 will execute on the previous terminal, not on the screen 'shared'.
How can I achieve that commands 2 and 3 will be executed on the current screen?
You may create a detached screen and then send commands to it. For example:
screen -d -m -S shared
screen -S shared -X -p 0 stuff $'cd /home/nodejsapp\n'
screen -S shared -X -p 0 stuff $'node start.js app.js\n'
If you need to attach to the screen session afterwards, then you can add one more line:
screen -S shared -r
See screen's manual for more details:
screen options
screen commands
You could run a "server" as the program within screen, which reads commands to execute from the pseudoterminal which the "tty" program identifies. For instance, as I'm writing this, tty says (inside screen)
/dev/pts/2
and I can write to it by
date >/dev/pts/2
On the server side, the script would read line-by-line in a loop from the same device. (On some other systems, there are differently-named
devices for each side of the pseudoterminal).
That only needs a script which starts by getting the output of "tty", writing that to a file (which a corresponding client would know of), and then the client would read commands (whether from the keyboard or a file), write them to the server via the pty device.
That's doable with just a couple of shell scripts (a little more lengthy though than the usual answer here).

How do I pass a command to a screen session?

I'm writing a Linux shell script in which I need to start a new screen session, run a node.js server in the screen, then detach from the screen so that my server runs in the background.
Right now, these are the commands I run manually to do this:
screen
node server.js
[detach screen]
However, I need a way to automate this via the script, and if I just use the above commands in a shell script, it creates the screen and gets stuck there. How can I pass the "node server.js" command to the screen command?
EDIT:
Based on the suggested answer I have a script that works, except that I need to manually create a screen and detach from it before I run it. I tried adding screen -d -m as the first line to create a detached screen, but the script hangs after that line.
tempfile=$(mktemp)
indices=`tail -1 debug.log`
cat > $tempfile <<EOF
node server $indices
EOF
screen -X readbuf $tempfile
screen -X paste .
rm -f $tempfile
How can I create and detach a screen with the script?
This didn't work either:
screen
screen -d
It is as simple as this:
screen -md node server.js
This requires the command to run as a service (as it does), otherwise the screen stops immediately.
To optionally also set a name for the session (e.g. "session-name"):
screen -mdS session-name node server.js
You can then attach to the screen with:
screen -rd session-name
If you want to redirect all output to a file, you can do like this:
screen -mdS session-name bash -c 'node server.js &> output.log'
You can then monitor the output with e.g.:
tail -f output.log
You can list your running screens with:
screen -ls
or
screen -list
Example: Start a Python3 web server in a detached screen
Start a Python3 web server listening on port 8000 that serves files in the current directory, in a named
detached screen:
screen -mdS my-web-server python3 -mhttp.server
Or, with logging to a file:
screen -mdS my-web-server bash -c 'python3 -mhttp.server &> output.log'
For Python 2.x it looks like this:
screen -mdS my-web-server bash -c 'python -mSimpleHTTPServer &> output.log'
EDIT: Try this:
tempfile=$(mktemp)
cat > $tempfile <<EOF
node server.js
EOF
screen -S SessionName -X readbuf $tempfile; screen -RdS SessionName
screen -X paste .
rm -f $tempfile
It should create the temp file, create a screen called SessionName and runs the commands, then delete the temp file. Let me know if that works.

Resources