27

How do I fetch the current terminal name?

I mean to the name that ps shows in the TTY column, e.g.:

root@dor-desktop:/home/dor/Documents/LAMP_setup/webs_install/do/install# ps aux | egrep 'mysql|(^USER)'
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
dor       2238  0.2  1.9 448052 79796 ?        S    17:27   0:17 gedit /home/dor/Documents/LAMP_setup/webs_install/do/install/mysql.install /home/dor/Documents/LAMP_setup/webs_install/do/install/mysql.setup
root      4975  0.1  0.5 324984 22876 ?        S    18:12   0:04 gedit /usr/local/mysql/bin/mysqld_safe
root      8160  0.0  0.0   4108   664 pts/2    S    19:08   0:00 /bin/sh /usr/local/mysql/bin/mysqld_safe --skip-networking --skip-grant-tables --user=mysql --basedir=/usr/local/mysql --ledir=/usr/local/mysql/libexec
mysql     8279  0.0  0.4 146552 19032 pts/2    Sl   19:08   0:00 /usr/local/mysql/libexec/mysqld --basedir=/usr/local/mysql --datadir=/usr/local/mysql/var --user=mysql --skip-networking --skip-grant-tables --log-error=/usr/local/mysql/var/dor-desktop.err --pid-file=/usr/local/mysql/var/dor-desktop.pid --socket=/usr/local/mysql/mysql.sock --port=3306
root      8342  0.0  0.0   7632  1024 pts/2    R+   19:14   0:00 egrep --color=auto mysql|(^USER)

In the above example, I need to fetch pts/2 which is probably the name for the current terminal that executed those commands.

1

4 Answers 4

44
tty

Now I have to enter 30 characters where 3 would have been enough... :-)

6
  • 1
    apropos tty might have been instructive, too (-:
    – tripleee
    May 31, 2013 at 16:28
  • 2
    @tripleee If you know the result getting it usually seems easy. But this was a really hard one. I should upvote the question in order to kick him above the 125 rep points border so the he can offer the deserved bounty for my great effort... May 31, 2013 at 16:37
  • 2
    Your answer got me wondering where tty gets the name of the PTY or TTY. I ran strace -o spork tty to find out that it does a readlink on a /proc file: readlink("/proc/self/fd/0", "/dev/pts/5"..., 4095) = 10 It's great that /proc can be used to do such nifty things, but what did earlier Unixes, without a flexible /proc filesystem, do to get tty name?
    – user732
    May 31, 2013 at 16:39
  • You could simply explain what that command, is, what it does and what else you can do with it and whoooosh, it would be a better answer.
    – Bobby
    May 31, 2013 at 16:58
  • @Bobby Every answer can be made better. The questioner got his problem solved after two minutes; not so bad IMHO. Seriously, I have no idea what else you can do with tty. What it does is exactly what the question is about. I don't even get the difference between "what that command is" and "what it does". What "is" a command? But, hey, I don't want upvotes for nothing. If you write a clearly better answer (which mine may have prevented) then I will give a 50 rep bounty for that (as soon as it's possible i.e. in two days). May 31, 2013 at 17:07
4

Re: "You could simply explain what that command, is, what it does and what else you can do with it and whoooosh, it would be a better answer. – Bobby"

The Unix name of the current terminal (or console, as we oldsters use to sometimes also call it) is: /dev/tty which, can be used to easily create a new multi-line file from the command prompt thusly: cp /dev/tty README.md (hitting then puts the cursor on a new blank line where you can enter text, hit return again, enter a second line, etcetera. When finished entering lines, do a control-d which causes the cp command to exit and you will have made a multi-line file with a single command).

3
1

Re: "You could simply explain what that command, is, what it does and what else you can do with it and whoooosh, it would be a better answer. – Bobby"

OR we could really go crazy, and say "go look at the source code for more information." So I did.

To actually get the name in tty.c, an auxilliary function ttyname is called on STDIN_FILENO. Both of these are defined in unistd.h (for proof, run grep "STDIN_FILENO\|ttyname" /usr/include/unistd.h), which is pulled into tty.c through #include "system.h" (go here to see system.h).

Now ttyname is an external dependency defined in glib_c/sysdeps/posix/ttyname.c. It, in turn, fstats file descriptor STDIN_FILENO (0), and uses the function gettyname to actually retrieve a pointer to the name of the tty. fstat ends up leading to an INLINE_SYSCALL in fxstat.c, which ends up invoking an internal_syscall2, and at this point I'm outta luck. I don't really know what that does.

But, I believe it invokes the stat functionality on fd 0. It does all this, making sure not to stop at "stdin" or something like that. Either way, you can achieve the same behavior by looking at

stat /dev/stdin # -> /proc/self/fd/0
stat /proc/self/fd/0 # -> /dev/pts/<some number>

Then /dev/pts/<some number> is your tty.

Update

I'm trying to get to the bottom of it all, but I won't be as detailed as above. So far I've deduced that the syscall indirection ends up at a function called vfs_fstat which then calls the function fdget_raw which immediately calls __fget_light. This uses a macro current which returns the result of get_current defined here:

static __always_inline struct task_struct *get_current(void)
{                                                           
    return this_cpu_read_stable(current_task);              
}                                                           

Anyways, the task_struct has an entry files of type files_struct, which I guess keeps the list of files relevant to the current task. This is an array, and fd is an index into the array. To wrap all this up, we just need to find out what fd 0 really means in reference to this array (i.e. when a task is created, what actually gets put there). Then, we just need to see in the source if /proc/self accurately reflects that array, then we can be sure that what we think happens actually happens...

0

There is also Shell Parameter Expansion using the @P Operator. You can get the terminal device similar to $PS1 conventions:

$myvar='\l'
echo ${myvar@P}

This will expand \l to the basename of the current terminal device.

Reference: man bash

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .