6

My destkop file: /usr/share/applications/write-to-stdout-sterr.desktop

[Desktop Entry]
# created by autocreate-desktop-files-for-pycharm.py
Name=write-to-stdout-sterr
Icon=/usr/share/pixmaps/python2.7.xpm
Exec=/var/tmp/write-to-stdout-sterr.py
Terminal=false
Type=Application
Categories=Application

I run this script:

#!/usr/bin/python
import sys
import time
import datetime
sys.stdout.write('########### stdout %s\n' % datetime.datetime.now())
sys.stderr.write('+++++++++++ sdterr %s\n' % datetime.datetime.now())
time.sleep(120)

And chmod a+rx /var/tmp/write-to-stdout-sterr.py

If I call this via windows-key (launcher)

I want to see where stdout/stderr goes to.

root@aptguettler:~# ls -l /proc/$(pgrep -f write-to)/fd

Output:

insgesamt 0
lr-x------ 1 tguettler tguettler 64 Dez 16 12:42 0 -> /dev/null
lrwx------ 1 tguettler tguettler 64 Dez 16 12:42 1 -> 'socket:[346100]'
lrwx------ 1 tguettler tguettler 64 Dez 16 12:42 2 -> 'socket:[346100]'

Where does socket:[346100] go to? How can I see the other end of the socket?

Above question is a more precise version of this question: Where are error messages of failed application starts?

guettli
  • 1,777
  • use lsof. $(pgrep -f write-to) is your pid so lsof -i -a -p $(pgrep -f write-to). The NAME will point to where it goes. – Rinzwind Dec 16 '19 at 11:59
  • @Rinzwind lsof -i -a -p $(pgrep -f write-to) does not show anything. But the pgrep -f write-to works. – guettli Dec 16 '19 at 12:03
  • Are you really simply looking for a way to list the socket contents? – WinEunuuchs2Unix Dec 21 '19 at 22:12
  • @WinEunuuchs2Unix No, OP wants to find out how stdin/stdout in .desktop files works. And listing contents of sockets is not quite possible, as they don't quite store data, only pass it :) – Sergiy Kolodyazhnyy Dec 23 '19 at 10:06

2 Answers2

2

A socket is one endpoint of a bidirectional communication link. In your case both output streams write to one socket. You need two sockets in order to have "another end".

Where does socket:[346100] go to?

socket:[346100] is the socket itself. It is the process streams that go to the socket.

How can I see the other end of the socket?

To see the other endpoint, if present, look at the rem_address column of /proc/net/tcp having inode 346100.

  • 1
    Effectively, yes. This is the proper answer to what's been asked in the title, therefore +1 to the answer. Although I know, what OP is really looking for is to find out how stdout/stderr works for .desktop files and applications launched via that method. – Sergiy Kolodyazhnyy Dec 23 '19 at 10:01
2

OP's main goal is to find out how applications launched via Desktop Entries aka .desktop files. There is no answer to this question, as it is implementation-dependent, and the specifications to which I've linked above provide no standard as to how the standard streams should be redirected if at all.

For recent Ubuntu versions it is possible to find where those sockets connect. The number you see in the brackets is the inode within kernel's sockfs virtual filesystem. Per proc(5) manual:

          For file descriptors for pipes and sockets, the entries will
          be symbolic links whose content is the file type with the
          inode.  A readlink(2) call on this file returns a string in
          the format:

              type:[inode]

          For example, socket:[2248868] will be a socket and its inode
          is 2248868.  For sockets, that inode can be used to find more
          information in one of the files under /proc/net/.

However, there's a catch to that. In case of pipes, the inode for read and write end is the same. For socket pair - it's not guaranteed. However, this is likely a Unix domain socket, and we could in theory find it's file handle. Per Stephane Chazelas's answer, I've used ss -x on Ubuntu 18.04 virtual machine with XFCE to find the endpoint of the socket with .desktop file in your question, but slightly modified code:

#!/usr/bin/env python3
import sys
import time
import datetime
while True:
     sys.stdout.write('########### stdout %s\n' % datetime.datetime.now())
     sys.stderr.write('+++++++++++ sdterr %s\n' % datetime.datetime.now())
     time.sleep(1)

I did find the socket and it's end point apparently points to systemd socket:

adminx@bionicbeaver:~$ ls -l /proc/$(pgrep -f write-to-stdout )/fd/{0,1,2}
lr-x------ 1 adminx adminx 64 Dec 23 09:01 /proc/3773/fd/0 -> /dev/null
lrwx------ 1 adminx adminx 64 Dec 23 09:01 /proc/3773/fd/1 -> 'socket:[27437]'
lrwx------ 1 adminx adminx 64 Dec 23 09:01 /proc/3773/fd/2 -> 'socket:[26621]'
adminx@bionicbeaver:~$ ss -x | grep 27437
u_strESTAB 0      0             /run/systemd/journal/stdout 27438             * 27437                                                                          

Rightfully, so with the modified code you will see in the output of journalctl -f that the code writes to the syslog

Dec 23 09:49:47 bionicbeaver /usr/lib/gdm3/gdm-x-session[1441]: ########### stdout 2019-12-23 09:49:45.726394
Dec 23 09:49:47 bionicbeaver /usr/lib/gdm3/gdm-x-session[1441]: ########### stdout 2019-12-23 09:49:46.734060
Dec 23 09:49:47 bionicbeaver /usr/lib/gdm3/gdm-x-session[1441]: ########### stdout 2019-12-23 09:49:47.734603
Dec 23 09:49:47 bionicbeaver /usr/lib/gdm3/gdm-x-session[1441]: +++++++++++ sdterr 2019-12-23 09:49:45.726459
Dec 23 09:49:47 bionicbeaver /usr/lib/gdm3/gdm-x-session[1441]: +++++++++++ sdterr 2019-12-23 09:49:46.734122
Dec 23 09:49:47 bionicbeaver /usr/lib/gdm3/gdm-x-session[1441]: +++++++++++ sdterr 2019-12-23 09:49:47.734787

Notice that the desktop manager gdm is responsible for passing those messages. If you perform a bit of filtering on /proc as described in a related question on pipes you will see that multiple processes connect to this same socket as clients, and gdm acts as sort of server for that.

However, this is not a consistent behavior. Per Gille's and Stephane's answers, finding the other end of socket pair is possible only with kernel above 3.3, and as I mentioned before it is up to desktop environment/window manager implementation to decide how to wire the standard streams. On a different Debian-based distro with Mutter the same code maps only to /dev/null

$ ls -l /proc/$(pgrep -f /var/tmp/write-to-stdout-sterr.py)/fd/{0,1,2}
lr-x------ 1 xie xie 64 Dec 23 16:38 /proc/16975/fd/0 -> /dev/null
l-wx------ 1 xie xie 64 Dec 23 16:38 /proc/16975/fd/1 -> /dev/null
l-wx------ 1 xie xie 64 Dec 23 16:38 /proc/16975/fd/2 -> /dev/null

In conclusion, do not expect this to be portable at all. Be explicit if you want to obtain the stdout or stderr of applications launched via the Desktop Entries.

Sergiy Kolodyazhnyy
  • 105,154
  • 20
  • 279
  • 497