[Updated1] Ich habe eine Shell, die TCP -Kernelparameter in einigen Funktionen ändert, aber jetzt muss diese Shell im Docker-Container ausgeführt werden. Das heißt, die Shell muss wissen, dass sie in einem Container läuft und stoppt den Kernel konfigurieren.
Nun bin ich mir nicht sicher, wie ich das erreichen kann, hier ist der Inhalt von /proc/self/cgroup
im Container:
9:hugetlb:/
8:perf_event:/
7:blkio:/
6:freezer:/
5:devices:/
4:memory:/
3:cpuacct:/
2:cpu:/docker/25ef774c390558ad8c4e9a8590b6a1956231aae404d6a7aba4dde320ff569b8b
1:cpuset:/
Obige Flags können verwendet werden, um herauszufinden, ob dieser Prozess in einem Container ausgeführt wird?
[Updated2]: Ich habe auch festgestellt Das Bestimmen, ob ein Prozess in lxc/Docker ausgeführt wird, aber es scheint nicht zu funktionieren, ist der Inhalt in /proc/1/cgroup
meines Containers in diesem Fall:
8:perf_event:/
7:blkio:/
6:freezer:/
5:devices:/
4:memory:/
3:cpuacct:/
2:cpu:/docker/25ef774c390558ad8c4e9a8590b6a1956231aae404d6a7aba4dde320ff569b8b
1:cpuset:/
Nein/lxc/containerid
Um in einem Docker-Container nachzuschauen, ob Sie sich in einem Docker-Container befinden oder nicht, können Sie über /proc/1/cgroup
erfolgen. Als dieser Beitrag schlägt Ihnen folgendes vor:
Außerhalb eines Docker-Containers enden alle Einträge in /proc/1/cgroup
mit /
, wie Sie hier sehen können:
[email protected]:~$ cat /proc/1/cgroup
11:name=systemd:/
10:hugetlb:/
9:perf_event:/
8:blkio:/
7:freezer:/
6:devices:/
5:memory:/
4:cpuacct:/
3:cpu:/
2:cpuset:/
In einem Docker-Container gehören einige der Kontrollgruppen zu Docker (oder LXC):
[email protected]:~$ docker run busybox cat /proc/1/cgroup
11:name=systemd:/
10:hugetlb:/
9:perf_event:/
8:blkio:/
7:freezer:/
6:devices:/docker/3601745b3bd54d9780436faa5f0e4f72bb46231663bb99a6bb892764917832c2
5:memory:/
4:cpuacct:/
3:cpu:/docker/3601745b3bd54d9780436faa5f0e4f72bb46231663bb99a6bb892764917832c2
2:cpuset:/
Docker erstellt .dockerenv
und ( in v1.11 entfernt) - Dateien am oberen Rand der Verzeichnisstruktur des Containers, so dass Sie überprüfen möchten, ob diese vorhanden sind..dockerinit
So etwas sollte funktionieren.
#!/bin/bash
if [ -f /.dockerenv ]; then
echo "I'm inside matrix ;(";
else
echo "I'm living in real world!";
fi
Wir verwenden den sched (/ proc/$ PID/sched) der proc, um die PID des Prozesses zu extrahieren. Die PID des Prozesses innerhalb des Containers unterscheidet sich von der PID des Hosts (eines Nicht-Containersystems).
Beispielsweise gibt die Ausgabe von/proc/1/sched für einen Container Folgendes zurück:
[email protected]:~# cat /proc/1/sched | head -n 1
bash (5276, #threads: 1)
Während eines Hosts ohne Container:
$ cat /proc/1/sched | head -n 1
init (1, #threads: 1)
Dies hilft zu unterscheiden, ob Sie sich in einem Container befinden oder nicht. Sie können zB:
if [[ ! $(cat /proc/1/sched | head -n 1 | grep init) ]]; then {
echo in docker
} else {
echo not in docker
} fi
Thomas 'Lösung als Code:
running_in_docker() {
(awk -F/ '$2 == "docker"' /proc/self/cgroup | read non_empty_input)
}
Hinweis
Die Variable read
mit einer Dummy-Variablen ist eine einfache Sprache für Erzeugt dies eine Ausgabe?. Es ist eine kompakte Methode, um eine möglicherweise verbose grep
oder awk
in ein test eines Musters zu verwandeln.
Was für mich funktioniert, ist nach der Inode-Nummer des '/' zu suchen. Innerhalb des Dockers ist es eine sehr hohe Zahl . Außerhalb des Dockers ist es eine sehr niedrige Zahl wie '2' . Ich denke, dieser Ansatz würde auch vom verwendeten Dateisystem abhängen.
Beispiel
# ls -ALi / | sed '2!d' |awk {'print $1'}
1565265
$ ls -ALi / | sed '2!d' |awk {'print $1'}
2
In einem Skript:
#!/bin/bash
INODE_NUM=`ls -ALi / | sed '2!d' |awk {'print $1'}`
if [ $INODE_NUM == '2' ];
then
echo "Outside the docker"
else
echo "Inside the docker"
fi
Wir mussten Prozesse ausschließen, die in Containern ausgeführt werden. Statt jedoch nur nach Andockgruppen zu suchen, haben wir uns entschlossen, /proc/<pid>/ns/pid
mit dem init-System unter /proc/1/ns/pid
zu vergleichen. Beispiel:
pid=$(ps ax | grep "[r]edis-server \*:6379" | awk '{print $1}')
if [ $(readlink "/proc/$pid/ns/pid") == $(readlink /proc/1/ns/pid) ]; then
echo "pid $pid is the same namespace as init system"
else
echo "pid $pid is in a different namespace as init system"
fi
Oder in unserem Fall wollten wir einen Einzeiler, der einen Fehler generiert, wenn sich der Prozess NICHT in einem Container befindet
bash -c "test -h /proc/4129/ns/pid && test $(readlink /proc/4129/ns/pid) != $(readlink /proc/1/ns/pid)"
die wir von einem anderen Prozess aus ausführen können, und wenn der Exit-Code Null ist, wird die angegebene PID in einem anderen Namespace ausgeführt.
Ich habe ein kleines Python-Skript erstellt. Hoffe, jemand findet es nützlich. :-)
#!/usr/bin/env python3
#@author Jorge III Altamirano Astorga 2018
import re
import math
total = None
meminfo = open('/proc/meminfo', 'r')
for line in meminfo:
line = line.strip()
if "MemTotal:" in line:
line = re.sub("[^0-9]*", "", line)
total = int(line)
meminfo.close()
print("Total memory: %d kB"%total)
procinfo = open('/proc/self/cgroup', 'r')
for line in procinfo:
line = line.strip()
if re.match('.{1,5}:name=systemd:', line):
dockerd = "/sys/fs/cgroup/memory" + \
re.sub("^.{1,5}:name=systemd:", "", line) + \
"/memory.stat"
#print(dockerd)
memstat = open(dockerd, 'r')
for memline in memstat:
memline = memline.strip()
if re.match("hierarchical_memory_limit", memline):
memline = re.sub("[^0-9]*", \
"", memline)
total = math.floor(int(memline) / 2**10)
memstat.close()
procinfo.close()
print("Total available memory to the container: %d kB"%total)