I am trying to automate some manual steps using python, i am opening new command prompt using os.popen and running docker compose up .. its opening new cmd and running the docker command, now i want run the next set of commands after docker command is up ... python script has to wait till that time, i tried with below code but its not working.
I tried with subprocess.Popen which has wait method but its not opening new cmd,it is running in python script running command prompt only ..
p=os.popen("Start cmd /K docker-compose up")
p.wait
I think the "start" command in windows cmd runs a process that launches a child process with the rest of the line as parameter, then finishes immediately. I guess that is why it does not wait until the docker-compose finishes (or whatever command you write after "start").
Example with Process IDs (PIDs):
Your python program (PID 1) runs the command "start cmd /K docker-compose up". The start process has PID 2. Start launches the "cmd /K docker-compose up" (a new process with PID 3). Start finishes. Your programs waits until PID 2 ends (it already ended so continues without waiting).
What you really wanted in the example is to wait until PID 3 finishes not PID 2.
Probably you can get the real PID of the child process with some tricks and then wait until it completes but you should consider if you really need the docker-compose to run in a separate window.
Related
Got a script for activating a python venv and running a server in the background, but right now I am trying to keep the pid when I start the process and then kill the process with pid after I am done. However, it is not all the time is gets killed.
My question is, can I run the process with a name, then killing it by using pkill name after? and how will that look
#!/bin/sh
ROOT_DIR=$(pwd)
activate(){
source $ROOT_DIR/.venv/bin/activate
python3 src/server.py -l & pid=$! # <== This is the process
python3 src/client.py localhost 8080
}
activate
sleep 10
kill "$pid"
printf "\n\nServer is done, terminating processes..."
You can run programs with a specific command name by using the bash buildin exec. Note that exec replaces the shell with the command so you have to run it in a subshell environment like:
( exec -a my_new_name my_old_command ) &
However, it probably won't help you much because this sets the command line name, which is apparently different from the command name. So executing the above snippet will show your process as "my_new_name" for example in top or htop, but pkill and killall are filtering by the command name and will thus not find a process called "my_new_name".
While it is interesting, how one can start a command with a different name than the executable, it is most likely not the cause of your problem. PIDs never change, so I assume that the problem lays somewhere different.
My best guess is that the server binds a socket to listen on a specific port. If the program is not shutdown gracefully but killed the port number remains occupied and is only freed by the kernel after some time during some kind of kernel garbage collect. If the program is restarted after a short period of time it finds the port already been occupied and prints a misleading message, that says it is already running. If that is indeed the cause of your problem I would strongly consider implementing a way to graceful shutdown the server. (may be already closing the socket in a destructor or something similar could help)
I think you should have to use systemd for this case:
https://github.com/torfsen/python-systemd-tutorial
I've coded a stock trading bot in Python3. I have it hosted on a server (Ubuntu 18.10) that I use iTerm to SSH into. Wondering how to keep the script actively running so that when I exit out of my session it won't kill the active process.
Basically, I want to SSH into my server, start the script then close out and come back into it when the days over to stop the process.
You could use nohup and add & at the end of your command to safely exit you session without killing original process. For example if your script name is script.py:
nohup python3 script.py &
Normally, when running a command using & and exiting the shell afterwards, the shell will terminate the sub-command with the hangup signal (kill -SIGHUP <pid>). This can be prevented using nohup, as it catches the signal and ignores it so that it never reaches the actual application.
You can use screen
sudo apt-get install screen
screen
./run-my-script
Ctrl-A then D to get out of your screen
From there you will be able to close out your ssh terminal. Come back later and run
screen -ls
screen -r $screen_running
The screen running is usually the first 5 digits you see after you've listed all the screens. You can see if you're script is still running or if you've added logging you can see where in the process you are.
Using tmux is a good option. Alternatively you could run the command with an & at the end which lets it run in the background.
https://tmuxcheatsheet.com/
I came here for finding nohup python3 script.py &
Right solution for this thread is screen OR tmux. :)
I am using pexpect to run a start command on an in-house application. The start command starts a number of processes. As the processes are starting one by one in the background everything looks good, but when the 'start' process finishes and the pexpect process ends, the processes that have been started also die.
child = pexpect.spawn('foo start')
child.logfile = log
child.wait()
For this scenario, I can use nohup and it works as expected.
child = pexpect.spawn('bash -c "nohup foo start"')
However, there is also an installer for the same in-house application that has the same issue, part of the installation is to start the processes. The installer is interactive and requires input, so nohup will not work.
How can I prevent the processes that are started by the installer from dying when the pexpect session ends?
Note: The start and install processes work fine when executed from a standard terminal session. They are not tied to the session in any way.
I couldn't find much in the documentation about it, but including the "ignore_sighup=True" option in the spawn command fixed my issue.
child = pexpect.spawn('foo start', ignore_sighup=True)
I am running Python tornado web application from terminal by typing the command python app.py when I close the terminal, the app stops. Is there anyway I can still run the app on a port such that closing terminal wouldn't affect it? Because I don't want to keep the terminal open.
Try nohup. In your case, it should be sufficient to run:
nohup python app.py &
Take note of the number shown as result of this command; it is the pid of the process, and it is used to terminate the process itself, simply by killing it. Suppose that 3456 is the pid of the process, so this command will terminate your application:
kill -9 3456
In case you lose the pid, it can be retrieved using this command:
ps -A | grep app.py
where app.py is the Python script file (the same used in the initial nohup command).
Anyway, for further information you can take a look here.
I would like to run an asynchronous program on a remote linux server indefinitely. This script doesn't output anything to the server itself(other than occasionally writing information to a mysql database). So far the only option I have been able to find is the nohup command:
nohup script_name &
From what I understand, nohup allows the command to run even after I log out of my SSH session while the '&' character lets the command run in the background. My question is simple: is this the best way to do what I would like? I am only trying to run a single script for long periods of time while occasionally stopping it to make updates.
Also, if nohup is indeed the best option, what is the proper way to terminate the script when I need to? There seems to be some disagreement over what is the best way to kill a nohup process.
Thanks
What you are basically asking is "How do I create a daemon process?" What you want to do is "daemonize", there are many examples of this floating around on the web. The process is basically that you fork(), the child creates a new session, the parent exits, the child duplicates and then closes open file handles to the controlling terminal (STDIN, STDOUT, STDERR).
There is a package available that will do all of this for you called python-daemon.
To perform graceful shutdowns, look at the signal library for creating a signal handler.
Also, searching the web for "python daemon" will bring up many reimplementations of the common C daemonizing process: http://code.activestate.com/recipes/66012/
If you can modify the script, then you can catch SIGHUP signals and avoid the need for nohup. In a bash script you would write:
trap " echo ignoring hup; " SIGHUP
You can employ the same technique to terminate the program: catch, say, a SIGUSR1 signal in a handler, set a flag and then gracefully exit from your main loop. This way you can send this signal of your choice to stop your program in a predictable way.
There are some situations when you want to execute/start some scripts on a remote machine/server (which will terminate automatically) and disconnect from the server.
eg: A script running on a box which when executed 1) takes a model and copies it to a custer (remote server) 2) creates a script for running a simulation with the wodel and push it to server 3) starts the script on the server and disconnect 4) The duty of the script thus started is to run the simulation in the server and once completed (will take days to complete) copy the results back to client.
I would use the following command:
ssh remoteserver 'nohup /path/to/script `</dev/null` >nohup.out 2>&1 &'
eg:
echo '#!/bin/bash
rm -rf statuslist
mkdir statuslist
chmod u+x ~/monitor/concat.sh
chmod u+x ~/monitor/script.sh
nohup ./monitor/concat.sh &
' > script.sh
chmod u+x script.sh
rsync -azvp script.sh remotehost:/tmp
ssh remoteshot '/tmp/script.sh `</dev/null` >nohup.out 2>&1 &'
Hope this helps ;-)
That is the simplest way to do it if you want to (or have to) avoid changing the script itself. If the script is always to be run like this, you can write a mini script containing the line you just typed and run that instead. (or use an alias, if appropriate)
To answer you second question:
$ nohup ./test &
[3] 11789
$ Sending output to nohup.out
$jobs
[1]- Running emacs *h &
[3]+ Running nohup ./test &
$ kill %3
$ jobs
[1]- Running emacs *h &
[3]+ Exit 143 nohup ./test
Ctrl+c works too, (sends a SIGINT) as does kill (sends a SIGTERM)