# Ssh / popen / stdin weirdness

**URL:** <https://www.ruby-forum.com/t/ssh-popen-stdin-weirdness/104538>\
**Category:** Ruby\
**Created:** [May 19, 2007, 3:56am UTC](https://www.ruby-forum.com/t/ssh-popen-stdin-weirdness/104538 "2007-05-19T03:56:46Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![mikec](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/977dab/32.png) [@mikec](https://www.ruby-forum.com/u/mikec)\
**Post date:** [May 19, 2007, 3:56am UTC](https://www.ruby-forum.com/t/ssh-popen-stdin-weirdness/104538/1 "2007-05-19T03:56:46Z")

</div>

Sorry I can’t figure out how to find the cause of this myself. I’m sure  
there’s some article somewhere I’m not finding.

on RHEL4 u3, ruby 1.8, create:

===  
app.rb:

my\_pipe = IO.popen("ssh foreign-host ‘cat filename’)  
file\_contents = my\_pipe.read  
my\_pipe.close

inp = $stdin.read  
puts "returning " + inp

====

Run this app from this host (call it ServerB):  
ruby app.rb \<\<EOF  
hi there  
EOF

You get “returning hi there”, as expected.

* * *

Now, from ServerA (public keys have been pushed), run:

ssh ServerB ‘ruby app.rb’ \<\<EOF  
hi there  
EOF

## it fails, in that inp receives nothing from $stdin.

now, go back to app.rb, remove the first three lines so there’s no call  
to IO.pipe.

run it again, it works.

why does $stdin get “moved” when the app is called remotely and opens a  
pipe?

---

<div class="post-metadata">

**Author:** ![mikec](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/977dab/32.png) [@mikec](https://www.ruby-forum.com/u/mikec)\
**Post date:** [May 19, 2007, 4:12am UTC](https://www.ruby-forum.com/t/ssh-popen-stdin-weirdness/104538/2 "2007-05-19T04:12:47Z")

</div>

> ====
> 
> run it again, it works.
> 
> why does $stdin get “moved” when the app is called remotely  
> and opens a pipe?

SSH doesn’t fork a TTY when a command is given. Try calling ssh with  
the -t flag.  
-Doug

---

<div class="post-metadata">

**Author:** ![mikec](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/977dab/32.png) [@mikec](https://www.ruby-forum.com/u/mikec)\
**Post date:** [May 19, 2007, 5:17am UTC](https://www.ruby-forum.com/t/ssh-popen-stdin-weirdness/104538/3 "2007-05-19T05:17:51Z")

</div>

“Mike C.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

> Sorry I can’t figure out how to find the cause of this myself. I’m  
> sure there’s some article somewhere I’m not finding.

What’s happening is that the standard input is getting read by the ssh  
process itself, if the standard input is ready when the ssh process is  
running.

Try this on ServerB: (i.e. where you ran it locally and it succeeded)

echo hi there | ruby abb.rb

I’m betting that you won’t get “hi there” being returned, because “hi  
there” will end up as standard input to the ssh process.

To fix this, change this line:  
my\_pipe = IO.popen("ssh foreign-host ‘cat filename’)  
into:  
my\_pipe = IO.popen(“ssh foreign-host ‘cat filename’ \< /dev/null”)

Now ssh won’t pull on your standard input stream. If you prefer to  
put the bit of input redirection at the front of the line, you can  
also do something like this:  
my\_pipe = IO.popen(“echo|ssh foreign-host ‘cat filename’”)  
or even this, though I think it’s less portable:  
my\_pipe = IO.popen(“\</dev/null ssh foreign-host ‘cat filename’”)

Now, why this makes a difference running it locally versus remotely  
I’m not entirely sure, especially since I’d think that a here document  
would be sent all at once even to a local process, but when I was  
running it locally just by typing lines and then control-D, the line  
returned was the first line typed after the ssh process had completed.

---

<div class="post-metadata">

**Author:** ![mikec](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/977dab/32.png) [@mikec](https://www.ruby-forum.com/u/mikec)\
**Post date:** [May 21, 2007, 6:04pm UTC](https://www.ruby-forum.com/t/ssh-popen-stdin-weirdness/104538/4 "2007-05-21T18:04:19Z")

</div>

> my\_pipe = IO.popen("ssh foreign-host ‘cat filename’)

Not sure if this is causing a problem, but you are missing a closeing  
quote in this line.
