# Utility library for spawning remote asynchronous tasks
from nepi.util import server
import getpass
+import logging
class STDOUT:
"""
def remote_spawn(command, pidfile, stdout='/dev/null', stderr=STDOUT, stdin='/dev/null', home=None, create_home=False, sudo=False,
host = None, port = None, user = None, agent = None,
ident_key = None, server_key = None,
- tty = False):
+ tty = False, hostip = None):
"""
Spawn a remote command such that it will continue working asynchronously.
'gohome' : 'cd %s ; ' % (server.shell_escape(home),) if home else '',
'create' : 'mkdir -p %s ; ' % (server.shell_escape,) if create_home else '',
}
+
(out,err),proc = server.popen_ssh_command(
cmd,
host = host,
agent = agent,
ident_key = ident_key,
server_key = server_key,
- tty = tty
+ tty = tty ,
+ hostip = hostip
)
if proc.wait():
- raise RuntimeError, "Failed to set up application: %s %s" % (out,err,)
+ raise RuntimeError, "Failed to set up application on host %s: %s %s" % (host, out,err,)
return (out,err),proc
+@server.eintr_retry
def remote_check_pid(pidfile,
host = None, port = None, user = None, agent = None,
- ident_key = None, server_key = None):
+ ident_key = None, server_key = None, hostip = None):
"""
Check the pidfile of a process spawned with remote_spawn.
user = user,
agent = agent,
ident_key = ident_key,
- server_key = server_key
+ server_key = server_key,
+ hostip = hostip
)
if proc.wait():
return None
+@server.eintr_retry
def remote_status(pid, ppid,
host = None, port = None, user = None, agent = None,
- ident_key = None, server_key = None):
+ ident_key = None, server_key = None, hostip = None):
"""
Check the status of a process spawned with remote_spawn.
"""
(out,err),proc = server.popen_ssh_command(
- "ps --ppid %(ppid)d -o pid | grep -c %(pid)d ; true" % {
+ "ps --pid %(pid)d -o pid | grep -c %(pid)d ; true" % {
'ppid' : ppid,
'pid' : pid,
},
user = user,
agent = agent,
ident_key = ident_key,
- server_key = server_key
+ server_key = server_key,
+ hostip = hostip
)
if proc.wait():
try:
status = bool(int(out.strip()))
except:
+ if out or err:
+ logging.warn("Error checking remote status:\n%s%s\n", out, err)
# Ignore, many ways to fail that don't matter that much
return NOT_STARTED
return RUNNING if status else FINISHED
+@server.eintr_retry
def remote_kill(pid, ppid, sudo = False,
host = None, port = None, user = None, agent = None,
- ident_key = None, server_key = None):
+ ident_key = None, server_key = None, hostip = None,
+ nowait = False):
"""
Kill a process spawned with remote_spawn.
Nothing, should have killed the process
"""
-
- (out,err),proc = server.popen_ssh_command(
- """
-%(sudo)s kill %(pid)d
-for x in 1 2 3 4 5 6 7 8 9 0 ; do
- sleep 0.1
- if [ `ps --pid %(ppid)d -o pid | grep -c %(pid)d` == `0` ]; then
+
+ if sudo:
+ subkill = "$(ps --ppid %(pid)d -o pid h)" % { 'pid' : pid }
+ else:
+ subkill = ""
+ cmd = """
+SUBKILL="%(subkill)s" ;
+%(sudo)s kill -- -%(pid)d $SUBKILL || /bin/true
+%(sudo)s kill %(pid)d $SUBKILL || /bin/true
+for x in 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 ; do
+ sleep 0.2
+ if [ `ps --pid %(pid)d -o pid | grep -c %(pid)d` == '0' ]; then
break
+ else
+ %(sudo)s kill -- -%(pid)d $SUBKILL || /bin/true
+ %(sudo)s kill %(pid)d $SUBKILL || /bin/true
fi
- sleep 0.9
+ sleep 1.8
done
-if [ `ps --pid %(ppid)d -o pid | grep -c %(pid)d` != `0` ]; then
- %(sudo)s kill -9 %(pid)d %(ppid)d
+if [ `ps --pid %(pid)d -o pid | grep -c %(pid)d` != '0' ]; then
+ %(sudo)s kill -9 -- -%(pid)d $SUBKILL || /bin/true
+ %(sudo)s kill -9 %(pid)d $SUBKILL || /bin/true
fi
-""" % {
+"""
+ if nowait:
+ cmd = "( %s ) >/dev/null 2>/dev/null </dev/null &" % (cmd,)
+
+ (out,err),proc = server.popen_ssh_command(
+ cmd % {
'ppid' : ppid,
'pid' : pid,
- 'sudo' : 'sudo -S' if sudo else ''
+ 'sudo' : 'sudo -S' if sudo else '',
+ 'subkill' : subkill,
},
host = host,
port = port,
user = user,
agent = agent,
ident_key = ident_key,
- server_key = server_key
+ server_key = server_key,
+ hostip = hostip
)
# wait, don't leave zombies around
proc.wait()
-