How docker interacts with your terminal - linux

I'm curious about how dockerized processes interact with the terminal from which you run docker run.
From some research I done, I found that when you run a container without -t or -i, the file descriptors of the process are:
// the PID of the containerized process is 16198
~$ sudo ls -l /proc/16198/fd
total 0
lrwx------ 1 root root 64 Jan 18 09:28 0 -> /dev/null
l-wx------ 1 root root 64 Jan 18 09:28 1 -> 'pipe:[242758]'
l-wx------ 1 root root 64 Jan 18 09:28 2 -> 'pipe:[242759]'
I see that the other ends of those pipes are of the containerd-shim process that spawned the containerized process. We know that once that process will write something to its STDOUT, it will show up on the terminal from which you ran docker run. Further, when you run a container with -t and look at the open FDs of the process:
~$ sudo ls -l /proc/17317/fd
total 0
lrwx------ 1 root root 64 Jan 18 09:45 0 -> /dev/pts/0
lrwx------ 1 root root 64 Jan 18 09:45 1 -> /dev/pts/0
lrwx------ 1 root root 64 Jan 18 09:45 2 -> /dev/pts/0
So now the container has a pseudo-tty slave as STDIN, STDOUT and STDERR. Who has the master side of that slave? Listing the FDs of the parent containerd-shim we can now see that it has a /dev/ptmx open:
$ sudo ls -l /proc/17299/fd
total 0
lr-x------ 1 root root 64 Jan 18 09:50 0 -> /dev/null
l-wx------ 1 root root 64 Jan 18 09:50 1 -> /dev/null
lrwx------ 1 root root 64 Jan 18 09:50 10 -> 'socket:[331340]'
l--------- 1 root root 64 Jan 18 09:50 12 -> /run/docker/containerd/afb8b7a1573c8da16943adb6f482764bb27c0973cf4f51279db895c6c6003cff/init-stdin
l--------- 1 root root 64 Jan 18 09:50 13 -> /run/docker/containerd/afb8b7a1573c8da16943adb6f482764bb27c0973cf4f51279db895c6c6003cff/init-stdin
lrwx------ 1 root root 64 Jan 18 09:50 14 -> /dev/pts/ptmx
...
So I suppose that the containerd-shim process interacts with the container process using this pseudo-terminal system. By the way, even in this case you can't interact with the process, since I didn't ran the container with -i.
So one question is: what difference does it make if containerd-shim interacts with the process using a pipe or using a pseudo-terminal subsystem?
Another question is, how do containerd-shim rolls this data to the terminal from which I ran docker run

Related

'cannot open shared object file' with OpenOnload

I have built and installed https://github.com/Xilinx-CNS/onload shared lib.
Then I am trying:
onload ping 8.8.8.8
Got this error:
ERROR: ld.so: object 'libonload.so' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored.
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=110 time=29.2 ms
But it works with sudo onload ping 8.8.8.8:
oo:ping[724989]: netif_tcp_helper_alloc_u: ENODEV. This error can occur if:
- no Solarflare network interfaces are active/UP, or they are running packed stream firmware or are disabled, and
- there are no AF_XDP interfaces registered with sfc_resource Please check your configuration.
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=110 time=50.4 ms
Can someone help me, how I can achieve this command working without sudo? For example, onload nc -l $PORT works without sudo, but ping do not.
Some debug information:
sudo find / -name libonload.so:
/usr/lib/x86_64-linux-gnu/libonload.so
cat /etc/ld.so.conf
include /etc/ld.so.conf.d/*.conf
cat /etc/ld.so.conf.d/*.conf
/usr/lib/x86_64-linux-gnu/libfakeroot
/usr/local/lib
/usr/local/lib/x86_64-linux-gnu
/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu
/lib32
/usr/lib32
sudo ldconfig -v:
...
/usr/lib/x86_64-linux-gnu/libfakeroot:
libfakeroot-0.so -> libfakeroot-tcp.so
/usr/local/lib:
/lib/x86_64-linux-gnu:
...
libonload_ext.so.2 -> libonload_ext.so.2.0.0
libonload.so -> libonload.so
...
...
ls -l /usr/lib/x86_64-linux-gnu | grep onload
-rwxr-xr-x 1 root root 9528312 Mar 3 01:17 libonload.so
-rw-r--r-- 1 root root 106222 Mar 3 01:17 libonload_ext.a
lrwxrwxrwx 1 root root 18 Mar 3 01:17 libonload_ext.so -> libonload_ext.so.2
lrwxrwxrwx 1 root root 22 Mar 3 01:17 libonload_ext.so.2 -> libonload_ext.so.2.0.0
-rwxr-xr-x 1 root root 31344 Mar 3 01:17 libonload_ext.so.2.0.0
ls -l /lib/x86_64-linux-gnu | grep onload
-rwxr-xr-x 1 root root 9528312 Mar 3 01:17 libonload.so
-rw-r--r-- 1 root root 106222 Mar 3 01:17 libonload_ext.a
lrwxrwxrwx 1 root root 18 Mar 3 01:17 libonload_ext.so -> libonload_ext.so.2
lrwxrwxrwx 1 root root 22 Mar 3 01:17 libonload_ext.so.2 -> libonload_ext.so.2.0.0
-rwxr-xr-x 1 root root 31344 Mar 3 01:17 libonload_ext.so.2.0.0
/lib$ ls -l | grep x86_64-linux-gnu
drwxr-xr-x 35 root root 36864 Mar 3 01:17 x86_64-linux-gnu
/usr/lib$ ls -l | grep x86_64-linux-gnu
drwxr-xr-x 35 root root 36864 Mar 3 01:17 x86_64-linux-gnu
The most likely reason is the ping application uses setuid but the Onload library isn't installed with that. Running ping will effectively promote the application to root user to allow the creation of a raw socket but the library will be loaded as the regular user and so it can't be used. Running as the root user avoids this since the library is loaded as the root user to start with.
I don't think GitHub version of Onload supports loading with setuid for the Onload library but you can set this yourself using chmod +s <libpath>. It's worth pointing out that ping isn't accelerated by Onload since the library will only accelerate UDP and TCP socket and pipes so you wouldn't see any benefit from this.

Can't run dmidecode on docker container

I am trying to run command dmidecode in my docker container,
docker run --device /dev/mem:/dev/mem -it jin/ubu1604
However, it claims that there is no permission
root#bd1062dfd8ab:/# dmidecode
# dmidecode 3.0
Scanning /dev/mem for entry point.
/dev/mem: Operation not permitted
root#bd1062dfd8ab:/# ls -l /dev
total 0
crw--w---- 1 root tty 136, 0 Jan 7 03:21 console
lrwxrwxrwx 1 root root 11 Jan 7 03:20 core -> /proc/kcore
lrwxrwxrwx 1 root root 13 Jan 7 03:20 fd -> /proc/self/fd
crw-rw-rw- 1 root root 1, 7 Jan 7 03:20 full
crw-r----- 1 root kmem 1, 1 Jan 7 03:20 mem
drwxrwxrwt 2 root root 40 Jan 7 03:20 mqueue
crw-rw-rw- 1 root root 1, 3 Jan 7 03:20 null
lrwxrwxrwx 1 root root 8 Jan 7 03:20 ptmx -> pts/ptmx
drwxr-xr-x 2 root root 0 Jan 7 03:20 pts
crw-rw-rw- 1 root root 1, 8 Jan 7 03:20 random
drwxrwxrwt 2 root root 40 Jan 7 03:20 shm
lrwxrwxrwx 1 root root 15 Jan 7 03:20 stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Jan 7 03:20 stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Jan 7 03:20 stdout -> /proc/self/fd/1
crw-rw-rw- 1 root root 5, 0 Jan 7 03:20 tty
crw-rw-rw- 1 root root 1, 9 Jan 7 03:20 urandom
crw-rw-rw- 1 root root 1, 5 Jan 7 03:20 zero
This confused me. Since I was able to run dmidecode -t system on the host (ubuntu 14.04) fine.
I even followed some advice and set the permission on dmidecode executable
setcap cap_sys_rawio+ep /usr/sbin/dmidecode
It still doesn't work.
Any ideas?
UPDATE
Based on David Maze's answer, the command should be
run --device /dev/mem:/dev/mem --cap-add SYS_RAWIO -it my/ubu1604a
Do this only when you are going to trust what runs in container. For example, if you are test installation procedure on a pristine OS.
Docker provides an isolation layer, and one of the major goals of Docker is to hide details of the host's hardware from containers. The easiest, most appropriate way to query low-level details of the host's hardware is from a root shell on the host, ignoring Docker entirely.
The actual mechanism of this is by restricting Linux capabilities. capabilities(7) documents that you need CAP_SYS_RAWIO to access /dev/mem, so in principle you can launch your container with --cap-add SYS_RAWIO. You might need other capabilities and/or device access to make this actually work, because Docker is hiding the details of what you're trying to access as a design goal.

/dev/ttyACM0 File does not exist while Postfix pipe

When I run script as regular user manually, everything is OK. But if an email is received and piped into Go script, I can not open serial port because file does not exist.
postfix 1239 1025 0 13:20 ? 00:00:00 pipe -n watchParadox -t unix flags=F user=watch argv=/usr/local/bin/watch -paradox
watch 1240 1239 0 13:20 ? 00:00:00 /usr/local/bin/watch -paradox
Script is running under watch user who has been added to dialout group, postfix user, just to be sure, is in dialout also.
In my script I ran ls -la command to find out which files do truly exist:
drwxr-xr-x 6 root root 380 Feb 25 13:19 .
dr-xr-xr-x. 18 root root 4096 Feb 22 17:53 ..
lrwxrwxrwx 1 root root 11 Feb 25 13:19 core -> /proc/kcore
lrwxrwxrwx 1 root root 13 Feb 25 13:19 fd -> /proc/self/fd
crw-rw-rw- 1 root root 1, 7 Feb 25 13:19 full
drwxr-xr-x 2 root root 0 Feb 25 13:19 hugepages
lrwxrwxrwx 1 root root 28 Feb 25 13:19 log -> /run/systemd/journal/dev-log
drwxrwxrwt 2 root root 40 Feb 25 13:19 mqueue
crw-rw-rw- 1 root root 1, 3 Feb 25 13:19 null
lrwxrwxrwx 1 root root 8 Feb 25 13:19 ptmx -> pts/ptmx
drwxr-xr-x 2 root root 0 Feb 25 13:19 pts
crw-rw-rw- 1 root root 1, 8 Feb 25 13:19 random
drwxrwxrwt 2 root root 40 Feb 25 13:19 shm
lrwxrwxrwx 1 root root 15 Feb 25 13:19 stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Feb 25 13:19 stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Feb 25 13:19 stdout -> /proc/self/fd/1
crw-rw-rw- 1 root root 5, 0 Feb 25 13:19 tty
crw-rw-rw- 1 root root 1, 9 Feb 25 13:19 urandom
I am certain following file exists but is not shown when postfix pipe is executed.
crw-rw---- 1 root dialout 166, 0 25. úno 13.19 ttyACM0
I tried chmod 777 on the file but no luck in that department. Opening file via https://github.com/tarm/serial library which uses Go function:
os.OpenFile("ttyACM0", syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0666)
results with
ttyACM0: no such file or directory
The problem is not the path because I tried relative (using chdir) and absolute with same exact outcome.
I even disabled SELinux which is not what I want to do but in search of solution I try anything.
Code is OK because manual execution of the script passes through properly. I think there is something wrong with Linux settings.
The correct path the ttyACM0 is /dev/ttyACM0. You define a udev rules to set the file mode when it attaches.
If that is not reachable from your program, it might be the case that your program runs chrooted().
It seems like it was truly Linux problem and some underlying fabrics of it which I do not understand. I was running Fedora25 but the problem does not occur on Debian8.

How to see which file are in use in Linux

I have a question how can I see which file are in use in linux. To be honest this OS is not the normal version of linux it is very crippled so for example there is no command like "lsof". I found command "strace" but this is no what I looking for. I hear that I can list this file with hacking kernel?
I want to see which file are in use because on this machine is a little free space and I want to delete file which are no in use when the program is running.
I'm sorry for my weak english.
You can inspect the open files by process by walking the /proc virtual filesystem
Every process running has an entry in /proc/PID. There's a directory in each process directory called 'fd', that represents the processes currently opened file descriptors. These appear as links to the actual resources.
e.g. on a VM I have running
root#wvm:/proc/1213/fd# pidof dhclient
1213
root#wvm:/proc/1213/fd# cd /proc/1213/fd
root#wvm:/proc/1213/fd# ls -l
total 0
lrwx------ 1 root root 64 Apr 8 09:11 0 -> /dev/null
lrwx------ 1 root root 64 Apr 8 09:11 1 -> /dev/null
lrwx------ 1 root root 64 Apr 8 09:11 2 -> /dev/null
lrwx------ 1 root root 64 Apr 8 09:11 20 -> socket:[4687]
lrwx------ 1 root root 64 Apr 8 09:11 21 -> socket:[4688]
l-wx------ 1 root root 64 Apr 8 09:11 3 -> /var/lib/dhcp/dhclient.eth0.leases
lrwx------ 1 root root 64 Apr 8 09:11 4 -> socket:[4694]
lrwx------ 1 root root 64 Apr 8 09:11 5 -> socket:[4698]
root#wvm:/proc/1213/fd#
Looking at the kernel process information for 'dhclient' - I find its pid, and then look in the fd subdirectory for this process id. It has a small set of open descriptors - stdin, stdout and stderr ( 0,1,2 ) have all been attached to /dev/null , there's four sockets open, but file descriptor 3 is attached to a data file /var/lib/dhcp/dhclient.eth0.leases
So you could duplicate the functionality of lsof using shell tools to walk /proc and filter out the file names from these links.
Are you able to use "top" command? if so then this should show you the list of all the top OS utilizing operations running on linux. You can do
ps -ef|grep <process_no>
this would give the details of it. Either can stop that process or kill it using
kill -9 <process no>
Use the lsof command to list all open files by process.

What's the exactly differences of /etc/init.d/something and /etc/rc.local [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 9 years ago.
Improve this question
When I need to create a autostartup task in Ubuntu. I always create a new file and write a bunch of commands into it. Next, I place this file in the /etc/init.d/ directory. Then, I set chmod 755 for this file. Finally, I execute the command line "update-rc.d file_name defaults" to activate it. And it works like a charm.
Recently, I found that there was another way to make it work the same to this above example. That is appending a new command line into /etc/rc.local (place it above the "exit 0" line).
So could you tell the difference between them ? Thank you very much !
To understand this problem, the first thing you should know is run level in *nix. There are total 6 run level in *nix. I won't show details of each run level, you can read more about it here.
Each run level have separate locations under /etc/:
% cuonglm at ~
% ls -l /etc/rc* -d
drwxr-xr-x 2 root root 4096 Feb 20 10:44 /etc/rc0.d
drwxr-xr-x 2 root root 4096 Feb 20 10:44 /etc/rc1.d
drwxr-xr-x 2 root root 4096 Feb 20 10:44 /etc/rc2.d
drwxr-xr-x 2 root root 4096 Feb 20 10:44 /etc/rc3.d
drwxr-xr-x 2 root root 4096 Feb 20 10:44 /etc/rc4.d
drwxr-xr-x 2 root root 4096 Feb 20 10:44 /etc/rc5.d
drwxr-xr-x 2 root root 4096 Feb 20 10:44 /etc/rc6.d
-rwxr-xr-x 1 root root 306 Feb 4 18:58 /etc/rc.local
drwxr-xr-x 2 root root 4096 Feb 4 19:01 /etc/rcS.d
Everytime your system boots, some scripts (which start with S) under the coressponding run level folder is executed. I.E if you boot in to run level 2, some scripts under /etc/rc2.d/ will executed. If you show content of these folder, you'll see that scripts is a symlink of scripts under /etc/init.d/.
% ls -l /etc/rc2.d/
total 4
-rw-r--r-- 1 root root 677 Jul 27 2012 README
lrwxrwxrwx 1 root root 20 Feb 19 11:26 S20kerneloops -> ../init.d/kerneloops
lrwxrwxrwx 1 root root 27 Feb 19 11:26 S20speech-dispatcher -> ../init.d/speech-dispatcher
lrwxrwxrwx 1 root root 20 Feb 19 11:26 S50pulseaudio -> ../init.d/pulseaudio
lrwxrwxrwx 1 root root 15 Feb 19 11:26 S50rsync -> ../init.d/rsync
lrwxrwxrwx 1 root root 15 Feb 19 11:26 S50saned -> ../init.d/saned
lrwxrwxrwx 1 root root 19 Feb 19 11:26 S70dns-clean -> ../init.d/dns-clean
lrwxrwxrwx 1 root root 18 Feb 19 11:26 S70pppd-dns -> ../init.d/pppd-dns
lrwxrwxrwx 1 root root 14 Feb 19 11:26 S75sudo -> ../init.d/sudo
lrwxrwxrwx 1 root root 17 Feb 20 10:44 S91apache2 -> ../init.d/apache2
lrwxrwxrwx 1 root root 22 Feb 19 11:26 S99acpi-support -> ../init.d/acpi-support
lrwxrwxrwx 1 root root 21 Feb 19 11:26 S99grub-common -> ../init.d/grub-common
lrwxrwxrwx 1 root root 18 Feb 19 11:26 S99ondemand -> ../init.d/ondemand
lrwxrwxrwx 1 root root 18 Feb 19 11:26 S99rc.local -> ../init.d/rc.local
This give you an ability to control your service to run under which runlevel. You can make your service run in only run level 2 and stop in others run level. But remember, Only one "runlevel" is executed on bootup, i.e. either runlevel 2 OR 3 OR 4 is executed, not 2 then 3 then 4.
So it leads you to the difference here. In each run level you boot in, after scripts of this run level is executed, the script /etc/rc.local is executed. It means that /etc/rc.local will run at the end of boot process, regardless of run level you boot in.

Resources