0

*Note that I'm trying to automate this to all be done from a script. Obviously I can do this easily manually.

Edit

After better understanding the question I can pose this question better. I am trying write commands to the stdin of a given terminal. They need to be accepted and run as commands in that terminal.

What I Need to Do:

I need to, from a shell script, open a terminal. We'll call it terminal 1. From terminal 1 I need to run a command.

Then, I need to open a second terminal (terminal 2) and run a second command and wait for that command to run to completion.

Now, the question is, how can I RETURN to terminal 1 and execute another command from within that terminal? (I then need to return to terminal 2 and execute another command but that should be an identical process to the answer for this).

There has to be some way to retain a process id for a terminal instance at the time of instantiation

gnome-terminal -e *command* <something to get PID of resulting terminal here?>

Related Answers I've Found (That don't have everything I'm looking for):

Disclaimer

I've been using Linux for quite awhile now and am comfortable working from with terminals. However, this is something I've never tried to do before. If I am just missing something fundamental about how terminals operate please point me in the direction of the necessary resources to get up to speed.

Bryce
  • 197
  • 1
  • 1
  • 13
  • 1
    Can you explain why this is your goal? In my experience, this is not a common need and it's possible (likely) that there is something else that achieve your goals without this method. – jeremysprofile Jun 11 '18 at 17:16
  • @jeremysprofile, I have a large simulation running on a VM. Part of the software is running in a container. In order to initialize and run you have to manually go back and forth between docker container and the VM and run commands. I'm trying to automate this process. While I should should be able to make it work without an answer to this question an answer would make it simpler and cleaner I believe – Bryce Jun 12 '18 at 15:02
  • Interesting. Unsure. You can get the PID of the gnome-terminal by running it in the background (putting a `&` after the command) and then `var=$!` will have `var` hold the pid of the gnome-terminal process. Then you could `wait $var` and etc. Unsure if this helps. Also unsure how gnome-terminals help you go back and forth between the container and its host. If this isn't sufficient, can you provide more detail about how you are running the terminals in the host and container? – jeremysprofile Jun 12 '18 at 16:27
  • @jeremysprofile. That is helpful, I didn't know the var=$! trick. Regarding the gnome-terminal, it's really that I want to go back to terminal 1 that has opened the container and have it change directories and execute a script. I realize you can log back in to a container from a different terminal. Which might be the solution here. – Bryce Jun 12 '18 at 19:50
  • @jeremysprofile, I just found this which accomplishes almost exactly what I was trying to do originally, I'll likely make it the answer to this post. The one caveat being I haven't gotten it to behave quite as I would expect as far as executing commands rather than just displaying text but I think its should work: https://serverfault.com/a/178470 – Bryce Jun 12 '18 at 19:54

2 Answers2

1

In order to write commands to a terminal from another program or terminal you must use a system input-output control system call (ioctl). (This may not always be the case but is is the solution I have found). I will also be presenting a solution in Python but I have cited other resources including a method in c below.

First, you need the process identifier (PID) of the terminal instance you wish to send commands to for it to execute. This can be determined in a few ways but the easiest way I found was via the following command:

ps -A | grep bash --color=always

This will output a list of open terminals and their PIDs and pts numbers. The easiest way I find to know which is the one you want is to open a terminal via your program, run the aforementioned command and the recently opened terminal will be the last on the list. I'm sure you can get more fancy with it if you need to be certain but that isn't the point of this question. You will see something like this, where the pts/# is what you're after

108514 pts/2    00:00:00 bash

Next use the following code and simply save it to a .py file of your choice, (credit for this code goes to the answer in the first link below, the Python one). Note that the example below is hard coded to send the "ls" command. Again, either change the hard coded command or make it not hard coded depending on your own preference and use case.

import fcntl
import sys
import termios

with open(sys.argv[1], 'w') as fd:
    for c in "ls\n":
        fcntl.ioctl(fd, termios.TIOCSTI, c)

Then, simply call the new function and pass it the following path based on the pts number found previously like so:

python <your_fcn_name_here).py /dev/pts/#

Worked fine for me on Ubuntu 14.04. I'll be trying it on CentOS soon. Didn't have to install any python libraries to do it.

Other Resources

This question has been posed differently here:

For more good information regarding IOCTLs:

Bryce
  • 197
  • 1
  • 1
  • 13
0

At the very end of the sh script, add

exec $SHELL

similar problem: https://askubuntu.com/questions/20330/how-to-run-a-script-without-closing-the-terminal

POLNET
  • 11
  • 1