开发者

"Pseudo-terminal will not be allocated because stdin is not a terminal" when running ssh through python without paramiko

I am running ssh from within Python without the use of an external library like Paramiko. I have my reasons for doing it this way instead 开发者_Python百科of through an external library.

Basically I am doing subprocess.Popen("ssh -t bla -- command")

I get the following message when doing this:

Pseudo-terminal will not be allocated because stdin is not a terminal.

The reason I am running it with -t is I want the remote command to terminate when I kill my python script.

When I try with -t -t (to force it), I get the following message:

tcgetattr: Inappropriate ioctl for device

Is there a way I can run my ssh command with -t through Python?


May I respectfully suggest that you are asking the wrong question, and that the right question might be something like "how do I make sure a sub process terminates when my python program terminates"

You could do some clever unix stuff like allocate a pty and make sure that you sub process uses this as std in out etc. so that the ssh command thinks that it's talking to a terminal rather than a pipe, but this is probably not what you really want to do.


To terminate the remote command when the python script gets killed, you may (as an alternative to the -t option to ssh) implement a workaround that uses a named pipe to convert "EOF to SIGHUP" when the stdin of sshd is being closed (see Bug 396 - sshd orphans processes when no pty allocated).

# sample code in Bash

# press ctrl-d for EOF
ssh localhost '
TUBE=/tmp/myfifo.fifo
rm -f "$TUBE"
mkfifo "$TUBE"
#exec 3<>"$TUBE"

<"$TUBE" sleep 100 &  appPID=$!

# cf. "OpenSSH and non-blocking mode", 
# http://lists.mindrot.org/pipermail/openssh-unix-dev/2005-July/023090.html
#cat >"$TUBE"
#socat -u STDIN "PIPE:$TUBE"
dd of="$TUBE" bs=1 2>/dev/null
#while IFS="" read -r -n 1 char; do printf '%s' "$char"; done > "$TUBE"

#kill -HUP -$appPID 
kill $appPID

rm -f "$TUBE"
'


It sounds like you're really asking for the inverse of the old nohup command; that is to say some way to ensure that the remote command responds to the HUP (hang-up) signal that's generated by the TTY (PTY or psuedo-tty) driver when the underlying connection to it is closed.

Personally I suspect that Paramiko is going to be far better than trying to manage this with the subprocess module. You can have Paramiko open the connection, allocate the pty and execute your commands without any cruft; and the code to use your existing known_hosts and identity files (private keys) is relatively straightforward.

This recipe Copy files over SSH using paramiko at ActiveState shows the basics of loading ssh known_hosts, using identity files and interacting with any ssh agent you might be running. From there what you're asking for should simply be a matter of:

  • creating a session,
  • creating a channel,
  • getting a pty
  • and executing your remote command or invoking a shell and sending the your command to that shell using the stdin file like object it returns.

You could also use the TwistedConch implementation of the SSH protocols. However, wrapping your head around the Twisted programming framework might be rather more difficult.

Here's an example of a simple ssh server in Twisted, with pty support: Twisted Conch in 60 Seconds: PTY Requests Here's an SO thread from only a week before yours was posted Best way to run remote commands thru ssh in Twisted? but that didn't cover pty related issues at all. Looking at the docs for twisted.conch.ssh.session suggests that it has pty support; but lists it as "Undocumented."

Of course you could even go with Pexpect, spawn a shell to your local ssh client and send your remote command through that. This would most closely emulate the way that you'd run the command from your own shell.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜