1 # Utility library for spawning remote asynchronous tasks
2 from nepi.util import server
7 Special value that when given to remote_spawn in stderr causes stderr to
8 redirect to whatever stdout was redirected to.
13 Process is still running
23 Process hasn't started running yet (this should be very rare)
26 def remote_spawn(command, pidfile, stdout='/dev/null', stderr=STDOUT, stdin='/dev/null', home=None, create_home=False, sudo=False,
27 host = None, port = None, user = None, agent = None, ident_key = None, tty = False):
29 Spawn a remote command such that it will continue working asynchronously.
32 command: the command to run - it should be a single line.
34 pidfile: path of a (ideally unique to this task) pidfile for tracking the process.
36 stdout: path of a file to redirect standard output to - must be a string.
38 stderr: path of a file to redirect standard error to - string or the special STDOUT value
39 to redirect to the same file stdout was redirected to. Defaults to STDOUT.
40 stdin: path of a file with input to be piped into the command's standard input
42 home: path of a folder to use as working directory - should exist, unless you specify create_home
44 create_home: if True, the home folder will be created first with mkdir -p
46 sudo: whether the command needs to be executed as root
48 host/port/user/agent/ident_key: see nepi.util.server.popen_ssh_command
51 (stdout, stderr), process
53 Of the spawning process, which only captures errors at spawning time.
54 Usually only useful for diagnostics.
56 # Start process in a "daemonized" way, using nohup and heavy
57 # stdin/out redirection to avoid connection issues
62 (out,err),proc = server.popen_ssh_command(
63 "%(create)s%(gohome)s rm -f %(pidfile)s ; ( echo $$ $PPID > %(pidfile)s ; %(sudo)s nohup %(command)s > %(stdout)s 2>%(stderr)s < %(stdin)s ) &" % {
70 'sudo' : 'sudo -S' if sudo else '',
72 'pidfile' : server.shell_escape(pidfile),
73 'gohome' : 'cd %s ; ' % (server.shell_escape(home),) if home else '',
74 'create' : 'mkdir -p %s ; ' % (server.shell_escape,) if create_home else '',
80 ident_key = ident_key,
85 raise RuntimeError, "Failed to set up application: %s %s" % (out,err,)
89 def remote_check_pid(pidfile,
90 host = None, port = None, user = None, agent = None, ident_key = None):
92 Check the pidfile of a process spawned with remote_spawn.
95 pidfile: the pidfile passed to remote_span
97 host/port/user/agent/ident_key: see nepi.util.server.popen_ssh_command
101 A (pid, ppid) tuple useful for calling remote_status and remote_kill,
102 or None if the pidfile isn't valid yet (maybe the process is still starting).
105 (out,err),proc = server.popen_ssh_command(
106 "cat %(pidfile)s" % {
113 ident_key = ident_key
121 return map(int,out.strip().split(' ',1))
123 # Ignore, many ways to fail that don't matter that much
127 def remote_status(pid, ppid,
128 host = None, port = None, user = None, agent = None, ident_key = None):
130 Check the status of a process spawned with remote_spawn.
133 pid/ppid: pid and parent-pid of the spawned process. See remote_check_pid
135 host/port/user/agent/ident_key: see nepi.util.server.popen_ssh_command
139 One of NOT_STARTED, RUNNING, FINISHED
142 (out,err),proc = server.popen_ssh_command(
143 "ps --ppid %(ppid)d -o pid | grep -c %(pid)d ; true" % {
151 ident_key = ident_key
160 status = bool(int(out.strip()))
162 # Ignore, many ways to fail that don't matter that much
164 return RUNNING if status else FINISHED
167 def remote_kill(pid, ppid, sudo = False,
168 host = None, port = None, user = None, agent = None, ident_key = None):
170 Kill a process spawned with remote_spawn.
172 First tries a SIGTERM, and if the process does not end in 10 seconds,
176 pid/ppid: pid and parent-pid of the spawned process. See remote_check_pid
178 sudo: whether the command was run with sudo - careful killing like this.
180 host/port/user/agent/ident_key: see nepi.util.server.popen_ssh_command
184 Nothing, should have killed the process
187 (out,err),proc = server.popen_ssh_command(
189 %(sudo)s kill %(pid)d %(ppid)d
190 for x in 1 2 3 4 5 6 7 8 9 0 ; do
192 if [ `ps --pid %(ppid)d -o pid | grep -c %(pid)d` == `0` ]; then
197 if [ `ps --pid %(ppid)d -o pid | grep -c %(pid)d` != `0` ]; then
198 %(sudo)s kill -9 %(pid)d %(ppid)d
203 'sudo' : 'sudo -S' if sudo else ''
209 ident_key = ident_key
212 # wait, don't leave zombies around