Hoffentlich ist diese Frage nicht zu allgemein. Ich bin sehr neu im Shell-Scripting und komme aus dem Bereich Computerarchitektur/nicht-Scripting-Programmierung. Mir ist bei den Skripten bei meiner Arbeit aufgefallen, dass sie selten geschrieben werden, indem man eine Unter-Shell um das gesamte Skript legt. Wenn ich die Skripte schreibe, schließe ich sie in eine Unter-Shell ein, da sie dann nicht mit anderen Skripten in Konflikt geraten, die meine aufrufen (nur für den Fall). Ist das nicht gängige Praxis, weil dieser Ansatz mit einem gewissen Mehraufwand verbunden ist? Es fällt mir schwer, dies online zu finden.
Beispiel:
#!/bin/bash
( #Start of subshell
echo "Some stuff here"
) #End of subshell
Antwort1
Subshells haben Overhead.
Auf meinem System betragen die minimalen Fork-Exec-Kosten (wenn Sie ein Programm von der Festplatte ausführen, wenn die Datei nicht kalt ist) etwa 2ms
und die minimalen Forking-Kosten betragen etwa 1ms
.
Bei Subshells sprechen Sie nur von den Forking-Kosten, da keine Datei exec
bearbeitet werden muss. Wenn die Subshells einigermaßen niedrig gehalten werden, 1ms
ist dies bei Programmen, die von Menschen bedient werden, ziemlich vernachlässigbar. Ich glaube, Menschen können nichts bemerken, was schneller passiert als 50ms
(und so lange dauert es normalerweise, bis moderne Interpreter von Skriptsprachen überhaupt starten (ich spreche hier python
von Ruby rvm
), wobei die neuesten nodejs
etwa benötigen 100ms
).
Bei Schleifen kommt es jedoch zu einer Aufsummierung, und dann möchten Sie vielleicht beispielsweise das recht gebräuchliche Bactick oder $()
Muster ersetzen, bei dem Sie return
etwas aus einer Funktion ausgeben, indem Sie es auf stdout drucken, damit die übergeordnete Shell es durch Bashismen wie diese erfassen kann printf -v
(oder ein schnelles externes Programm verwenden, um den gesamten Stapel zu verarbeiten).
DerBash-VervollständigungPaket vermeiden speziell diese Subshell-Kosten, indem sie über übergebene Variablennamen zurückkehren, mit einer Technik, die unter beschrieben wirdhttp://fvue.nl/wiki/Bash:_Passing_variables_by_reference
Vergleichen
time for((i=0;i<10000;i++)); do echo "$(echo hello)"; done >/dev/null
mit
time for((i=0;i<10000;i++)); do echo hello; done >/dev/null
sollte Ihnen eine gute Schätzung des Systemaufwands geben fork
.
Antwort2
Das Ausführen des hervorragenden Codes von PSkocik auf meinem System zeigte vernachlässigbare Ergebnisse.
Dieses Beispiel ist jedoch wirklich treffend - native Befehle vs. Subshell-Befehle:
MyPath="path/name.ext"
# this takes forever
time for((i=0;i<10000;i++)); do echo "$(basename ${MyPath} )"; done >/dev/null
#this is over 100x less time
time for((i=0;i<10000;i++)); do echo "${MyPath##*/}"; done >/dev/null