# Run a command in a new terminal window

**URL:** <https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739>\
**Category:** General Usage\
**Created:** [April 17, 2020, 6:06am UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739 "2020-04-17T06:06:19Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)\
**Post date:** [April 17, 2020, 6:06am UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739/1 "2020-04-17T06:06:19Z")

</div>

Hi all,

I’m trying to run a `Command` asynchronously and direct the output to a new terminal window. I understand that I can do this:

```julia
run(pipeline(`echo hello`, stdout="out.txt"))

```

which works to re-direct the output to a file, but what I’d really like is for the output to go to a new terminal window. Is this possible?

Cheers,

Colin

PS I’m on Ubuntu 18.04 if this makes any difference

---

<div class="post-metadata">

**Author:** ![robsmith11](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/robsmith11/32/29641_2.png) [@robsmith11](https://discourse.julialang.org/u/robsmith11)\
**Post date:** [April 17, 2020, 6:34am UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739/2 "2020-04-17T06:34:29Z")

</div>

You just want to see in the output of the command in another terminal window?

You could simply run `watch out.txt` or look into writing and reading from named pipes if you don’t want to write to disk.

---

<div class="post-metadata">

**Author:** ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)\
**Post date:** [April 17, 2020, 7:56am UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739/3 "2020-04-17T07:56:16Z")

</div>

> You could simply run `watch out.txt`

Yes, but if I call this command from Julia won’t it just start watching that file in the terminal that I am currently already running Julia in? The goal here is to re-direct the output to a new terminal window.

> writing and reading from named pipes

This is what I’m trying to do with the `pipeline` call, but I don’t know how to re-direct the output from the pipe to a new terminal window (which I would need to open programatically).

Apologies if I have misunderstood what you’re trying to suggest here.

---

<div class="post-metadata">

**Author:** ![jbrea](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jbrea/32/3879_2.png) [@jbrea](https://discourse.julialang.org/u/jbrea)\
**Post date:** [April 17, 2020, 8:33am UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739/4 "2020-04-17T08:33:15Z")

</div>

What about

```julia
run(`xterm -e watch cat out.txt`, wait = false)
run(pipeline(`echo hello`, stdout="out.txt"))

```

---

<div class="post-metadata">

**Author:** ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)\
**Post date:** [April 17, 2020, 1:15pm UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739/5 "2020-04-17T13:15:18Z")

</div>

This should work, thank you.

As an aside it does feel a bit hacky that I need to write via a file. Perhaps I might be able to run xterm in a separate pipeline and then write directly to that pipeline. I’ll have a play around and see what I can get working. Thanks again.

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [April 17, 2020, 2:11pm UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739/6 "2020-04-17T14:11:09Z")

</div>

What about using Distributed for this? The remote process could open a terminal, run your commands, and print the result into the terminal.

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [April 17, 2020, 2:25pm UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739/7 "2020-04-17T14:25:34Z")

</div>

If you can identify the tty of the other terminal you can redirect stdout/stderr to that one:

 ![Screenshot from 2020-04-17 16-25-10](https://global.discourse-cdn.com/julialang/original/3X/7/9/79067e20e9e41c2333175a48e408c07958661af9.png)

Edit: So from inside Julia your example would be

```julia
run(pipeline(`echo hello`, stdout="/dev/pts/14"))

```

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [April 17, 2020, 2:38pm UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739/8 "2020-04-17T14:38:45Z")

</div>

Assuming you’re on a UNIX-like system (which seems to be the case if you assume `xterm` to be available), you could use UNIX sockets instead of files.

```julia
# Make sure the UNIX socket does not exist yet
rm("/tmp/unix.sock", force=true)

# This is the code that the server will run
server_code = quote
    using Sockets
    foreach(println, eachline(accept(listen("/tmp/unix.sock"))))
end |> string

# Spawn a new julia process in a new terminal
julia = Base.julia_cmd()[1]
run(`xterm -e "$julia -e '$server_code'"`, wait=false)

# Connect to the socket and send some strings to it
using Sockets
s = connect("/tmp/unix.sock")
write(s, "Hello...\n"); flush(s); sleep(3)
write(s, "World!\n"); flush(s); sleep(3)

# It can be used to redirect the output of a pipeline, too
run(pipeline(`echo Hello from an other process`, stdout=s))
sleep(3)

# The server process will exit when this connection is closed
# ... so will the terminal.
close(s)

```

And if you’re not on a UNIX system, I guess this example could easily be adapted to TCP sockets (but you’d still have to handle the issue of how to spawn a terminal in a portable way)

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [April 17, 2020, 3:18pm UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739/9 "2020-04-17T15:18:02Z")

</div>

But perhaps I misunderstood: did you intend the process to be run as a server, receiving commands and processing them, and displaying output in the terminal window over and over again? Or just once?

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [April 17, 2020, 3:26pm UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739/10 "2020-04-17T15:26:47Z")

</div>

This would be a good way of emulating Stata’s interface, where you can scroll through your output without losing your writing space. OP, if this is what you are trying to do, check out jupyterlab’s console mode.

---

<div class="post-metadata">

**Author:** ![pixel27](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pixel27/32/8902_2.png) [@pixel27](https://discourse.julialang.org/u/pixel27)\
**Post date:** [April 17, 2020, 7:06pm UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739/11 "2020-04-17T19:06:12Z")

</div>

I just want to make sure you realize that what you are asking for is highly unusual and require some serious code to make happen.

Normally Julia runs in a terminal, it doesn’t know anything ABOUT the terminal it just knows it’s a terminal. If you just search for “terminal” in your Linux Distro’s application install you will probably see lots of different programs that provide a terminal:

- Byobu Terminal
- Deepin Terminal
- Xfce Terminal
- MATE Terminal
- LXTTerminal
- QTerminal
- etc…

It might even be in a text terminal like when you hit Ctrl Alt F2. Or it could be a terminal over a Telnet or SSH connection. Julia doesn’t really know, and doesn’t really care. Normally these terminals don’t communicate with each other and there is no “common” API to tell the terminal you want to duplicate a terminal and run a program in it.

So you are going to need to decide _which_ terminal application you want to interact with and actually launch it and tell it to run your program. i.e. your program will required that terminal X is installed on the machine. On my system I use `xfce4-terminal` for my terminals. Bringing up the `man` page for that shows that I can pass in a `-e` argument with the command to run.

So on my system I could execute `xfce4-terminal -e htop` to create a new terminal and run `htop` in it. When I exit `htop` the terminal automatically closes (which is probably specific to the xfce4-terminal program).

To make matters funner (worse) the output Julia would receive is the output from the terminal application NOT the output from the program running INSIDE the terminal. `xfce4-terminal` actually returns right after the new terminal is launched, so `run()` returns after the terminal is launch, NOT once the program running inside the terminal terminates.

So if you want your Julia program to receive data from the launch program you will need to tell that program to pass the data back to the original program somehow, sockets, TCP/IP, or a file would probably be the easiest.

---

<div class="post-metadata">

**Author:** ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)\
**Post date:** [April 20, 2020, 5:15am UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739/12 "2020-04-20T05:15:03Z")

</div>

This would definitely work, although it isn’t obvious how to obtain the tty of the terminal I’d like to direct the output to from within my current program. However, for my particular use-case it is feasible to just open the terminal myself, grab the tty, and then paste it into my program before I run it. So thanks, this is very helpful. Based on the other responses below, it seems obtaining the tty of a new terminal programmatically is going to be very much not straightforward.

---

<div class="post-metadata">

**Author:** ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)\
**Post date:** [April 20, 2020, 5:22am UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739/13 "2020-04-20T05:22:37Z")

</div>

Thanks for this. For my use-case, I actually think I can adapt this to work without the sockets. The Julia code in question uses a command to call a node.js program that sends data back to my original Julia program using a socket, but what I’m really trying to do is just ensure that the print statements from the node.js program print in a different terminal, as it makes things vastly easier to monitor in real-time when they don’t mix in with the print statements from my Julia program.

It looks like I can just adapt the `run` command from your code to call my node.js program inside a terminal emulator and this will accomplish what I’m after.

As it happens, I am also passing data from the node.js program back to Julia program via a domain socket, but this is ancillary to the issue with the print statements.

Thanks again.

---

<div class="post-metadata">

**Author:** ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)\
**Post date:** [April 20, 2020, 5:25am UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739/14 "2020-04-20T05:25:20Z")

</div>

Thanks for responding. No, that is much more complicated than what I’m after. I actually just have a Julia program that calls a node.js program via a `Command` to run asynchronously. The node.js program prints quite a lot of stuff, as does the Julia program, and it would be very helpful from a real-time monitoring perspective if the node.js print statements appear in a different window to the Julia print statements. As one of the other answerers points out, I can accomplish this just by calling the node.js program in my `Command` via a terminal emulator `xterm`.

---

<div class="post-metadata">

**Author:** ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)\
**Post date:** [April 20, 2020, 5:25am UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739/15 "2020-04-20T05:25:49Z")

</div>

Thanks for responding. I’ll have a look at what they do, although it does appear I’ve worked out a solution based on the responses in this thread.

---

<div class="post-metadata">

**Author:** ![colintbowers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/colintbowers/32/8033_2.png) [@colintbowers](https://discourse.julialang.org/u/colintbowers)\
**Post date:** [April 20, 2020, 5:28am UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739/16 "2020-04-20T05:28:50Z")

</div>

Thanks for taking the time to type such a lengthy response.

Yes, I was surprised at the responses this thread generated. For the general case, it is far less straightforward than I had envisaged, and as you say, would require quite a bit of work to implement.

Fortunately, it looks like for my particular use-case, I’ll be able to get what I want just by planting a call to a node.js program in my Command object inside a call to `xterm`. My main goal was just to get the print statements from the node.js program in a separate terminal. As it happens, I am also passing some data from the node.js program back to the Julia program, but I’m doing this via domain sockets, and have already got that part of the code working nicely.

---

<div class="post-metadata">

**Author:** ![jmboehm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmboehm/32/2263_2.png) [@jmboehm](https://discourse.julialang.org/u/jmboehm)\
**Post date:** [April 23, 2020, 11:51pm UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739/17 "2020-04-23T23:51:42Z")

</div>

I’m wondering whether it would make sense to create a package that helps with this. I can think of several applications (“watch” terminal for globals, table viewer, ascii plot output… essentially it would be a step towards a lightweight IDE).

From the discussion above, I imagine that this is likely to be fairly platform-specific. Is there a Windows equivalent to `tty`?

---

<div class="post-metadata">

**Author:** ![pixel27](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pixel27/32/8902_2.png) [@pixel27](https://discourse.julialang.org/u/pixel27)\
**Post date:** [April 24, 2020, 12:34am UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739/18 "2020-04-24T00:34:27Z")

</div>

> [@jmboehm](#):
>
> Is there a Windows equivalent to `tty` ?

I don’t believe so.

What would probably be easiest is create a TCP/IP listener on a random port. Spawn a Command Prompt or x-terminal that starts julia with a script to connect to localhost on that random port and echo everything it receives over the TCP/IP connection to the screen.

Then anything your program writes out the TCP/IP connection will show up on the other terminal. You could do this N times to spawn N different terminals. And except for the command to launch the terminal it would be all very OS non-specific.

---

<div class="post-metadata">

**Author:** ![Marcell\_Havlik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcell_havlik/32/37424_2.png) [@Marcell\_Havlik](https://discourse.julialang.org/u/Marcell_Havlik)\
**Post date:** [May 2, 2021, 2:01pm UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739/19 "2021-05-02T14:01:07Z")

</div>

Hey,

I saw this post and it helped me a lot so I share my version that came from these idea:

```julia
get_next_pts_nums(task_num) = begin # queriing the next terminal session IDs.
    pts_ls = read(`ls /dev/pts`, String)
    pts_nums = parse.(Int,split(pts_ls, '\n')[1:end-2])
    sort!(pts_nums)

    pts_ids = Vector{Int}(undef,task_num)
    x, i, j = 0, 1, 1 
    while i <= task_num
        while j <=length(pts_nums) && x == pts_nums[j]
            x+=1
            j+=1
        end
        pts_ids[i] = x
        x+=1
        i+=1
    end
    pts_ids
end
run_cmd(cmds::Vector{Cmd}, io) = for cmd in cmds run_cmd(cmd, io) end
run_cmd(cmd::Cmd, io) = begin
    run(`echo "+ $cmd"`, io, io, io)  
    run(cmd, io, io, io) 
end
run_in_terminal(cmd, t_id) = begin
    run(`gnome-terminal -- zsh`)
    pts_file = open("/dev/pts/$t_id", "w")
    run_cmd(cmd, pts_file)
end

```

For local run this is damn fast and clean:

```julia
macro aync_run(cmd)
    esc(:(for (i,t_id) in enumerate(get_next_pts_nums(length($cmd)))
        @async run_in_terminal($cmd[i], t_id)
    end))
end
# user, ip, cust_cmd = "testuser", "127.0.0.1", """echo "I am on the machine" """
@aync_run [`tty`,[`echo "haha whut"`, `tty`, `echo "I am on the machine"`, `echo "hell"`]]

```

Very ugly first try to run on different servers…

```julia
fn(user,ip) = begin
    term_pts = get_next_pts_nums(1)[1]
    run(`gnome-terminal -- zsh`)
    @async begin 
        term_io = open("/dev/pts/$term_pts","w")
        auth= `ssh -t $user@$ip`
        run(`$auth echo "hello cmd"`,term_io,term_io,term_io)
        run(`$auth tty`,term_io,term_io,term_io)
        run(`$auth echo helllo`,term_io,term_io,term_io)
    end
end
fn("testuser", "127.0.0.1")

```

I felt it would be too much time to parse the function with the macro add the terminal start and append the appropriate pts file for the run commands. So it is up to you to make it more clean. Also couldn’t agree on the best syntax, how do we want to use `@async_run` in terms of function calls, so broadcast on the vector of inputs or not… and so on.

Don’t forget I used “zsh” so replace it to you bash.  
Warning: We are calculating the “upcoming” terminal windows ID before it start, so there is a 0.000800 sec time till if someone else also start a windows from an external source, then there will be some fun overthere. 🙂

To cover the above mentioned issue, I tried to open my own pseudoterminal with the following commands but I didn’t know how to attach the next terminal on these file descriptors. I leave the efforst here, maybe someone will know how to finish.

```julia
pts_file = ccall((:open, "libc.so.6"), Cint, (Cstring, Cint), "/dev/ptmx",2) 
ret2 = ccall((:grantpt, "libc.so.6"), Cint, (Cint,), pts_file) 
ret3 = ccall((:unlockpt, "libc.so.6"), Cint, (Cint,), pts_file) 
pts_file_url = ccall((:ptsname, "libc.so.6"), Ptr{UInt8} , (Cint,), pts_file) 
@show unsafe_string(pts_file_url) # you can see the next terminal... but you already took the place... so... this isn't the next one already. 

```

I hope these help someone who also wants multiple terminal windows in julia and send the appropriate commands to the approriate terminal window. 🙂

---

<div class="post-metadata">

**Author:** ![zot](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zot/32/5817_2.png) [@zot](https://discourse.julialang.org/u/zot)\
**Post date:** [August 5, 2022, 9:09pm UTC](https://discourse.julialang.org/t/run-a-command-in-a-new-terminal-window/37739/20 "2022-08-05T21:09:32Z")

</div>

Did you get anywhere with this? I mean the pseudoterminal part…

I wonder if [TERMIOS.jl](https://github.com/kdheepak/TERMIOS.jl) might help?
