tty-command icon indicating copy to clipboard operation
tty-command copied to clipboard

Can't run shells in interactive mode

Open fsateler opened this issue 3 years ago • 13 comments

Describe the problem

Shells cannot be run with TTY::Command. Keyboard input is not read by the shell.

Steps to reproduce the problem

require 'tty-command'

cmd = TTY::Command.new(pty: true, printer: :quiet)

cmd.run(*ARGV)

Actual behaviour

(slightly edited to remove identifying information)

% bundle exec ruby ./test.rb dash
$ ls
oh no input is going nowhere
^C
$ ^C
$ but ctrl-c is handled?

^C
$ ctrl-d does nothing
^C
$ ^C
$ ^C
$ i have to kill this from another shell
zsh: terminated  bundle exec ruby ./test.rb

% bundle exec ruby ./test.rb bash
bash: cannot set terminal process group (84144): Inappropriate ioctl for device
bash: no job control in this shell
$ input does not go to the shell


ctrl c kills the process
^CTraceback (most recent call last):
	5: from ./test.rb:6:in `<main>'
	4: from ./.bundle/gems/ruby/2.6.0/gems/tty-command-0.9.0/lib/tty/command.rb:104:in `run'
	3: from ./.bundle/gems/ruby/2.6.0/gems/tty-command-0.9.0/lib/tty/command.rb:185:in `execute_command'
	2: from ./.bundle/gems/ruby/2.6.0/gems/tty-command-0.9.0/lib/tty/command/process_runner.rb:48:in `run!'
	1: from ./.bundle/gems/ruby/2.6.0/gems/tty-command-0.9.0/lib/tty/command/process_runner.rb:146:in `read_streams'
./.bundle/gems/ruby/2.6.0/gems/tty-command-0.9.0/lib/tty/command/process_runner.rb:146:in `join': Interrupt

 bundle exec ruby ./test.rb zsh
zsh: substitution failed
zsh: substitution failed
zsh: substitution failed
zsh: substitution failed
zsh: substitution failed
zsh: substitution failed
zsh: substitution failed
zsh: substitution failed
zsh: substitution failed
zsh: substitution failed
zsh: substitution failed
zsh: substitution failed
ls
I can't even get a prompt on zsh
^CTraceback (most recent call last):
	5: from ./test.rb:6:in `<main>'
	4: from ./.bundle/gems/ruby/2.6.0/gems/tty-command-0.9.0/lib/tty/command.rb:104:in `run'
	3: from ./.bundle/gems/ruby/2.6.0/gems/tty-command-0.9.0/lib/tty/command.rb:185:in `execute_command'
	2: from ./.bundle/gems/ruby/2.6.0/gems/tty-command-0.9.0/lib/tty/command/process_runner.rb:48:in `run!'
	1: from ./.bundle/gems/ruby/2.6.0/gems/tty-command-0.9.0/lib/tty/command/process_runner.rb:146:in `read_streams'
./.bundle/gems/ruby/2.6.0/gems/tty-command-0.9.0/lib/tty/command/process_runner.rb:146:in `join': Interrupt

% bundle exec ruby ./test.rb ssh $some_host
<snip MOTD banner>
$ ls
^CTraceback (most recent call last):
	5: from ./test.rb:6:in `<main>'
	4: from ./.bundle/gems/ruby/2.6.0/gems/tty-command-0.9.0/lib/tty/command.rb:104:in `run'
	3: from ./.bundle/gems/ruby/2.6.0/gems/tty-command-0.9.0/lib/tty/command.rb:185:in `execute_command'
	2: from ./.bundle/gems/ruby/2.6.0/gems/tty-command-0.9.0/lib/tty/command/process_runner.rb:48:in `run!'
	1: from ./.bundle/gems/ruby/2.6.0/gems/tty-command-0.9.0/lib/tty/command/process_runner.rb:146:in `read_streams'
./.bundle/gems/ruby/2.6.0/gems/tty-command-0.9.0/lib/tty/command/process_runner.rb:146:in `join': Interrupt

Expected behaviour

A working interactive shell.

Describe your environment

  • OS version: Debian linux sid
  • Ruby version: 2.6.6 and 2.7.1
  • TTY::Command version: 0.9.0

fsateler avatar Aug 24 '20 22:08 fsateler

Hi Felipe 👋

Thanks for rasing the issue and using tty-command.

Would you have time to investigate potential fix?

piotrmurach avatar Aug 24 '20 22:08 piotrmurach

It looks like the issue is that ProcessRunner only tries to write to stdin once when the command is started: https://github.com/piotrmurach/tty-command/blob/da308658f0cb96db78d5b3b25985fae0434973a0/lib/tty/command/process_runner.rb#L46

I think to be able to wrap interactive commands, we would need another thread to manage stdin.

ryansch avatar Sep 21 '20 16:09 ryansch

I was able to use https://github.com/stripe/subprocess to wrap an interactive command.

ryansch avatar Sep 21 '20 17:09 ryansch

@ryansch - mind providing a code snippet to show how you used subprocess to solve this?

codefriar avatar Dec 16 '20 05:12 codefriar

@codefriar I'd like this to be fixed in the tty-command project. I maintain many Ruby projects and have limited time. Thus I need help and encourage any contributions that get us closer to resolving this problem. Unfortunately, your comment doesn't get us in this direction. This is not the place to seek explanations on how to use other libraries and I suggest you open an issue in the other project.

piotrmurach avatar Dec 16 '20 21:12 piotrmurach

@piotrmurach My apologies. My initial read of @ryansch 's comment was that he'd gotten this to work in tty-command perhaps by utilizing the subprocess command. I was hoping to prompt him to share his fix for tty-command.

codefriar avatar Dec 16 '20 21:12 codefriar

Hi all, is this possible now? When I run a shell in a subprocess with pty: true (for example kubectl to open a shell in a pod in Kubernetes), the shell starts and I can press keys etc but when I press enter nothing happens in the shell. Any suggestion? Thanks!

vitobotta avatar Oct 29 '21 14:10 vitobotta

I just wrote https://github.com/outstand/dash/blob/cd7c740afd1dc7fa809afd630e8a50ee68e391ca/lib/state.rb#L65 to integrate Subprocess a bit more with this gem. At least this way I get similar logging output!

ryansch avatar Feb 11 '22 20:02 ryansch

@codefriar I finally did... ^

ryansch avatar Feb 11 '22 20:02 ryansch

I looked at the differences between tty-command and subprocess and I think subprocess works here because it gives the caller the ability to directly connect the spawned process to STDIN, STDOUT, STDERR.

ryansch avatar Feb 14 '22 13:02 ryansch

@ryansch Do you have any suggestions on helping tackle this issue in tty-command itself? I'm all for exposing streams to connect directly. This is important to solve. Any help would be really appreciated!

piotrmurach avatar Feb 14 '22 21:02 piotrmurach

I had originally thought about grafting subprocess into this gem but I think exposing the streams might be all we need. I'll see if I can't work up an experiment to test it.

ryansch avatar Feb 14 '22 22:02 ryansch