152

How would I 'attach' a console/terminal-view to an applications output so I can see what it may be saying?

How would I detach from an applications output without killing the application?

Normally if you fire up a talkative application using the command line you get to see all kinds of wonderful output. However, let’s say I have a particularly chatty programming running, like KINO, and I want to view its output at any given moment without restarting it through the command line. I cannot; at least I don't know how.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
aggitan
  • 2,094
  • 5
  • 19
  • 22
  • 1
    Do you have debug symbol in your process? Does it run in production environnement? And if so do you need it to NEVER been paused ? – yves Baumes Apr 03 '09 at 22:39
  • When I have bouts of stability issues with end user programs like kino (crashes and kills my sound) I want to be able to know how/why it crashed so I can work on fixing it. This isn't a program I'm developing but a technique I'd like to know for trouble shooting. I'll try your suggestion below. – aggitan Apr 04 '09 at 00:26

8 Answers8

384

I think I have a simpler solution here. Just look for a directory whose name corresponds to the PID you are looking for, under the pseudo-filesystem accessible under the /proc path. So if you have a program running, whose ID is 1199, cd into it:

$ cd /proc/1199

Then look for the fd directory underneath

$ cd fd

This fd directory hold the file-descriptors objects that your program is using (0: stdin, 1: stdout, 2: stderr) and just tail -f the one you need - in this case, stdout):

$ tail -f 1
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
licorna
  • 5,670
  • 6
  • 28
  • 39
  • 17
    I was unable to use `tail` as in my case the output was redirected to another process for input, but `more` showed me the current data. – Ωmega Sep 13 '13 at 14:38
  • @Ωmega - Wouldn't you be able to find the process that you're redirecting it into, and then tail it's stdin (/proc/#/0)? – TJ Biddle Sep 16 '13 at 23:14
  • In my environment actually `tail` didn't work at any scenario, only `head` and `more`... – Ωmega Sep 16 '13 at 23:41
  • 13
    One of the most riveting posts on this site! – robert Jan 23 '16 at 09:09
  • 3
    `more` is working for me. ubuntu 14.04 on a node process – Shih-Min Lee May 04 '16 at 07:01
  • 4
    This is not working for me with a java process which calls System.out.println. There is no output at all to /proc/[pid]/fd/1 – Nick May 13 '16 at 14:34
  • @Nick I don't know about Java but you might need to check JRE pid (or something like that). I won't be impressed if Java is heavily buffering stdout either. – licorna May 14 '16 at 15:08
  • 1
    Tried to create a reproduction using the below, but to no avail: ``` docker run -it --name container1 ubuntu bash -c -i "COUNT=0; while true; do echo Keep the dance floor beat going; ((COUNT++)); sleep 1; echo \"Count is: \${COUNT}\"; done;" ``` In another terminal: ``` docker exec -it container1 tail -f /proc/1/fd/1 ``` – JacobWuzHere Dec 27 '16 at 18:28
  • Sorry @JacobWuzHere. I don't have Docker experience, I'm not sure if Docker even uses the `proc` filesystem :( – licorna Dec 28 '16 at 11:07
  • 1
    Best discovery this year! This feature rocks! – eddyP23 Sep 14 '17 at 14:26
  • Wow this is so interesting. what happens for me is that doing a tail on a stdout of one process in python affects the input of another processes in python. for example keystrokes in a debug session of python are getting skipped. Very interesting. – Peter Moore May 23 '18 at 17:16
  • 1
    This will work if process has already allocated tty. You can check if tty is allocated or not using `ps' command. If it shows `?` in TTY column then no tty allocated, then there is nothing to check in /proc/PID/fd. – Tejas Sarade Jul 01 '18 at 09:06
  • @TejasSarade hm... my processes (running from bare Konsole or Tmux on Kubuntu 18.04) report that they have a TTY, but I can't tail or less the file descriptors anyway. At least, there seems to be nothing in them. – butla Nov 17 '18 at 01:47
  • For me, `tail` worked after I changed my current user to the owner of the process with `su proc_owner`. Even as `root` I was denied access. – akki Aug 21 '19 at 09:08
69

I was looking for this exact same thing and found that you can do:

strace -ewrite -p $PID

It's not exactly what you needed, but it's quite close.

I tried the redirecting output, but that didn't work for me. Maybe because the process was writing to a socket, I don't know.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Paul Scheltema
  • 1,993
  • 15
  • 25
  • 1
    thanks it works, but output is truncated, e.g. for ping: write(1, "64 bytes from 1.0.0.1: icmp_seq="..., 56) = 56 – izy Jul 24 '20 at 00:48
  • 4
    @izy you can specify a `-sLENGTH` flag to set a new buffersize (default 32). for more details, check https://unix.stackexchange.com/a/58601 – schetefan24 Sep 07 '21 at 07:50
23

There are a few options here. One is to redirect the output of the command to a file, and then use 'tail' to view new lines that are added to that file in real time.

Another option is to launch your program inside of 'screen', which is a sort-of text-based Terminal application. Screen sessions can be attached and detached, but are nominally meant only to be used by the same user, so if you want to share them between users, it's a big pain in the ass.

Don Werve
  • 5,100
  • 2
  • 26
  • 32
  • 1
    "There are a few options here. One is to redirect the output of the command to a file, and then use 'tail' to view new lines that are added to that file in real time." Can this be done with already running applications? – aggitan Apr 03 '09 at 21:23
  • 2
    You probably need tail -f $log_file to get the output as it is written in the file. Also, no, there is no way I know of to do that with an already running app. – Varkhan Apr 03 '09 at 21:29
  • @aggitan: No. For existing applications, you'll have to restart them, because they've already bound their I/O to the controlling terminal. – Don Werve Apr 03 '09 at 22:08
  • 1
    See http://unix.stackexchange.com/questions/31824/how-to-attach-terminal-to-detached-process – reinierpost Dec 02 '15 at 16:57
15

You can use reptyr:

sudo apt install reptyr
reptyr pid
Alexey Vazhnov
  • 1,291
  • 17
  • 20
Zhigang Zhang
  • 195
  • 1
  • 7
  • 3
    if `reptyr $PID` did not work try `sudo reptyr -T $PID` based on this [issue](https://github.com/nelhage/reptyr/issues/62#issuecomment-138653405) – weshouman Oct 25 '20 at 05:43
14

For me, this worked:

  1. Login as the owner of the process (even root is denied permission)

    ~$ su - process_owner
    
  2. Tail the file descriptor as mentioned in many other answers.

    ~$ tail -f /proc/<process-id>/fd/1 # (0: stdin, 1: stdout, 2: stderr)
    
akki
  • 2,021
  • 1
  • 24
  • 35
  • 3
    What if file descriptors point to a socket? `# ls -la /proc/24510/fd/1 lrwx------ 1 root root 64 Oct 31 08:34 /proc/24510/fd/1 -> socket:[444026]` – Fusion Sep 15 '21 at 13:55
8

How would I 'attach' a console/terminal-view to an applications output so I can see what it may be saying?

About this question, I know it is possible to catch the output, even when you didn't launch sceen command before launching the processus.

While I never tried it, I've found an interesting article which explains how to do using GDB (and without restarting your process).

redirecting-output-from-a-running-process

Basically:

  1. Check the open files list for your process, thanks to /proc/xxx/fd
  2. Attach your process with GDB
  3. While it is paused, close the file you are interested in, calling close() function (you can any function of your process in GDB. I suspect you need debug symbols in your process..)
  4. Open the a new file calling the create() or open() function. (Have a look in comments at the end, you'll see people suggest to use dup2() to ensure the same handle will be in use)
  5. Detach the process and let in run.

By the way, if you are running a linux OS on i386 box, comments are talking about a better tool to redirect output to a new console : 'retty' . If so, consider its use.

yves Baumes
  • 8,836
  • 7
  • 45
  • 74
3

I wanted to remotely watch a yum upgrade process that had been run locally, so while there were probably more efficient ways to do this, here's what I did:

watch cat /dev/vcsa1

Obviously you'd want to use vcsa2, vcsa3, etc., depending on which terminal was being used.

So long as my terminal window was of the same width as the terminal that the command was being run on, I could see a snapshot of their current output every two seconds. The other commands recommended elsewhere did not work particularly well for my situation, but that one did the trick.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
RedScourge
  • 976
  • 1
  • 8
  • 12
1

An even simpler option is cat:

cat /proc/<pid>/fd/1

Especially if tail does not work for you due to permission errors (even using sudo), or if the process to monitor display a progress bar using curses or an equivalent library.

caram
  • 1,494
  • 13
  • 21