问题
I have a code snippet something like this:
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(ip,port=Port, username=usr,password=Psw)
stdin, stdout, stderr= ssh.exec_command("watch -n1 ps")
print stdout.read(),stderr.read()
The problem here is I have to run watch
or any infinitely running command for 10 seconds and after that I should send SIGINT
(Ctrl + c) and print the status.
How do I do that?
回答1:
One way to get around this would be to open your own session, pseudo-terminal, and then read in a non-blocking fashion, using recv_ready()
to know when to read. After 10 seconds, you send ^C
(0x03) to terminate the running process and then close the session. Since you're closing the session anyway, sending ^C
is optional, but it may be useful if you want to keep the session alive and run commands multiple times.
import paramiko
import time
import sys
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(ip, port=Port, username=usr,password=Psw)
transport = ssh.get_transport()
session = transport.open_session()
session.setblocking(0) # Set to non-blocking mode
session.get_pty()
session.invoke_shell()
# Send command
session.send('watch -n1 ps\n')
# Loop for 10 seconds
start = time.time()
while time.time() - start < 10:
if session.recv_ready():
data = session.recv(512)
sys.stdout.write(data)
sys.stdout.flush() # Flushing is important!
time.sleep(0.001) # Yield CPU so we don't take up 100% usage...
# After 10 seconds, send ^C and then close
session.send('\x03')
session.close()
print
回答2:
The only way to transport signals is via terminal
, from ssh
man:
-t Force pseudo-tty allocation. This can be used to execute arbitrary screen-based programs on a remote machine, which can be very useful, e.g. when implementing menu services. Multiple -t options force tty allocation, even if ssh has no local tty.
For paramiko
check: http://docs.paramiko.org/en/1.16/api/channel.html
get_pty(*args, **kwds)
Request a pseudo-terminal from the server. This is usually used right after creating a client channel, to ask the server to provide
some basic terminal semantics for a shell invoked with invoke_shell. It isn’t necessary (or desirable) to call this method if you’re going to exectue a single command with exec_command.
来源:https://stackoverflow.com/questions/33910308/how-to-send-control-signals-using-paramiko-in-python