2017-02-15 3 views
2

Ich lerne gerade über Docker, und gehe durch die Dockerfile reference, speziell die RUN Anweisung. Es gibt zwei Formen von RUN - die Schale Form, die den Befehl in einer Shell ausgeführt wird, und die exec Form, die „ruft nicht eine Befehls-Shell“ (zitiert aus dem Hinweis Abschnitt). Wenn ich die Dokumentation richtig verstanden habe, lautet meine Frage: Wenn und wie kann Docker einen Befehl ohne Shell ausführen?Wie führt Docker einen Befehl aus, ohne eine Befehlsshell aufzurufen?

Beachten Sie, dass die Antworten auf Can a command be executed without a shell? nicht wirklich die Frage beantworten.

+1

Wie denkst du, dass die Shell selbst einen externen Befehl aufruft, nachdem sie die Kommandozeile geparst hat? Es * muss * eine Schnittstelle auf Betriebssystemebene sein, die es aufrufen kann. (Auch der Pass-a-String-to-a-Shell-Ansatz weist erhebliche Sicherheitsmängel auf. Shell-Injection-Schwachstellen lassen sich leicht vermeiden, wenn Sie Argumente außerhalb der Bandbreite entweder in der Umgebung oder an anderen Argv-Positionen übergeben System (string_to_parse) 'bietet keine bequeme Möglichkeit, beides zu tun. –

Antwort

4

cmd laufen Wenn ich Ihre Frage richtig verstanden, Sie fragen, wie kann etwas (insbesondere im Zusammenhang mit der Docker) ausgeführt werden, ohne eine Kommando-Shell aufrufen .

So wie die Dinge in dem Linux-Kernel ausgeführt werden, in der Regel the exec family of system calls.

Sie verwenden, um die ausführbare Datei Sie ausführen es den Weg wollen passieren und die Argumente, die über einen execl Anruf beispielsweise an sie übergeben werden müssen.


Dies ist tatsächlich, was Ihre Shell (sh, bash, ksh, zsh) sowieso unter der Haube tut. Sie können dies selbst beobachten, wenn Sie so etwas wie strace -f bash -c "cat /tmp/foo"

In der Ausgabe dieses Befehls laufen Sie so etwas wie dies sehen werden:

execve("/bin/cat", ["cat", "/tmp/foo"], [/* 66 vars */]) = 0 

Was wirklich los ist, dass bash up sieht cat in $PATH, es stellt dann fest, dass cat tatsächlich eine ausführbare Binärdatei ist, die unter /bin/cat verfügbar ist. Es ruft dann einfach über execve auf. und die richtigen Argumente, wie Sie oben sehen können.

Sie können trivialerweise ein C-Programm schreiben, das dasselbe tut. Dies ist, was ein solches Programm würde so aussehen:

#include<unistd.h> 

int main() { 

    execl("/bin/cat", "/bin/cat", "/tmp/foo", (char *)NULL); 

    return 0; 
} 

Jede Sprache mit diesen System von Schnittstellen Anrufe seine eigene Art und Weise zur Verfügung stellt. C tut, Python macht und Go, was auch das ist, was Docker zum größten Teil benutzt. Eine RUN Anweisung im Andockfenster führt wahrscheinlich zu einem dieser exec Aufrufe, wenn Sie docker build drücken.Sie können eine strace -f docker build und dann grep für exec Anrufe im Protokoll ausführen, um zu sehen, wie die Magie passiert.


Der einzige Unterschied zwischen etwas über eine Schale ausgeführt und direkt, dass Sie die fancy stuff auf alle Ihre Shell für Sie tun verlieren, wie variable Expansion, ausführbare usw.

+0

Ich war mir nicht sicher (deshalb suche ich [diese Frage] (http://unix.stackexchange.com/questions/203634/can-a-command-be-executed-witout-a-shell)). Sie sagen mir, dass es möglich ist, einen Befehl ohne Shell auszuführen? – dayuloli

+0

@dayuloli, ja tatsächlich ist es. Ich werde mit einem Beispiel in ein bisschen aktualisieren. – ffledgling

+0

@dayuloli siehe Update. – ffledgling

0

Ganz allgemein - docker run werden Behälter mit dem Standardprozess starten, wenn Docker exec ermöglicht es Ihnen, jeden Prozess Sie im Inneren des Behälters ausgeführt werden soll.

Zum Beispiel wird die Ausführung von Microsoft/IIS Container von docker run microsoft/iis Standardprozess ausgeführt, die Powershell ist.

Aber Sie können, indem Sie docker exec -i my_container cmd

See this answer for more details.

1

Ein Programm gesucht kann ein anderes Programm ohne Shell ausführen; Sie erstellen einfach einen neuen Prozess und laden eine ausführbare Datei darauf, sodass Sie die Shell dafür nicht benötigen. Die Shell wird benötigt, damit ein Benutzer ein Programm starten kann, da dies die Benutzerschnittstelle zum System ist. Außerdem kann ein Programm einen eingebauten Befehl wie cd oder rm ohne eine Shell nicht ausführen, weil es keine ausführbare Datei gibt (es gibt alternative Wege, dachte, aber nicht so einfach).

+0

Und Sie benötigen die Shell, um ein Skript auszuführen, da der Interpreter darin enthalten ist. –

+0

Vielen Dank für diese Antwort, es hat so viel für mich geklärt. Wenn ich also mein Docker-Image erstelle, wenn ich die Shell-Form von "RUN" verwende, wird es eine neue Shell erzeugen, die Shell den Befehl interpretieren lassen und dann den interpretierten Befehl ausführen. Wenn ich das Formular * exec * verwende, wird der aktuelle Prozess, der 'docker run' ausführt, einen neuen Prozess erstellen und die ausführbare Datei an ihn übergeben. – dayuloli

+0

Genau. So etwas ohne eine Shell zu laufen ist leichter, aber mit ein paar weniger Fähigkeiten. Wenn der Befehl, den Sie ausführen möchten, eine ausführbare Datei (binär, kein Skript) ist und Sie nicht etwas in den Befehlszeilenargumenten (wie Umgebungsvariablen) übersetzen müssen, dann wäre die Shell nur eine Last. –

Verwandte Themen