bash: Einige Probleme bei der Verwendung von read <<< “$ VARIABLE” auf einer schreibgeschützten Root-Partition. Bekannte Problemumgehungen?

11

Zufällig musste ich mein Skript ATA-ID-zu-Gerätename verwenden (hier zu finden: /server/244944/linux-ata-errors-translating-to-a-device-name/) 426561 # 426561 ) auf einer schreibgeschützten / Partition. Falls Sie neugierig sind, handelt es sich um eine Ubuntu-Wiederherstellungskonsole, mit der Sie auf Ihre /Partition zugreifen können, die jedoch standardmäßig schreibgeschützt bereitgestellt wird. Ich freue mich darüber, denn sonst hätte ich wahrscheinlich nie herausgefunden, dass sich mein Skript aufgrund einer bestimmten Zeile auf einem R / O-System seltsam verhält:

IFS=: read HostMain HostMid HostSub <<< "$HostFull"

Dies funktioniert nicht , wenn keine Schreibberechtigung vorliegt. Ich hätte allerdings nicht angenommen, dass es scheitern würde. Aber anscheinend der <<<Bediener nicht erfordert eine temporäre Datei irgendwo zu schreiben.

Aber gibt es eine Möglichkeit, die Erstellung einer temporären Datei zu umgehen, oder gibt es eine Möglichkeit, anzugeben, wohin die Datei geschrieben wird? In der Ubuntu-Wiederherstellungskonsole gibt es - seltsamerweise - Schreibberechtigungen für das /runVerzeichnis, so dass dies ausreichen würde, wenn ich irgendwie "sagen" könnte read, dass die temporäre Datei an einen anderen Ort als gewöhnlich geschrieben werden soll.

Syntax-Fehler
quelle
2
@gniourf_gniourf Nein, das "Öffnen eines Dateideskriptors" wäre kein Problem (warum sollte es?) und /dev/fdhat nichts damit zu tun. <<<ist jedoch der Schuldige, weil es eine temporäre Datei erstellt (die irgendwo geschrieben werden muss).
Gilles 'SO - hör auf böse zu sein'

Antworten:

8

Ein Array kann die Zeichenfolge analysieren, ohne dass eine temporäre Datei erforderlich ist. Vergessen Sie nicht, das Globbing auszuschalten.

set -f
IFS=: Hosts=($HostFull)
HostMain=${Hosts[0]}
HostMid=${Hosts[1]}
HostSub=${Hosts[2]}
set +f
xae
quelle
2
oder auch ohne IFS, wenn Sie sicher sind, dass keine Leerzeichen vorhanden sind $HostFull: Hosts=( ${HostFull//:/ } ). Oder auch wenn es Leerzeichen gibt: HostMain=${HostFull%%:*}; HostMid=${HostFull#*:}; HostSub=${HostMid#*:}; HostMid=${HostMid%:*}(oder ähnliches, ich werde verwirrt :D).
gniourf_gniourf
Sie haben Recht, da Sie zeigen, dass die Parametererweiterung schwierig ist ...
xae
4

Ich stimme @gniourf_gniourf zu, Sie benötigen wahrscheinlich Schreibzugriff, aber nicht auf die Dateideskriptoren, höchstwahrscheinlich eine Datei.

Sie können dies testen, indem Sie die Ausführung Ihres Befehls in der schreibgeschützten Partition verfolgen.

{ strace -p "$$" & sleep 1; read var1 <<< "hi"; sleep 1; kill "$1"; }

Das Obige wird straceauf der Bash-Shell (Prozess $$) ausgeführt. Es schläft dann für 1 Sekunde und läuft dann die readvon der HERE STRING. Ich habe die Saite "hi"in diese Position gebracht. Ich dann sleepnoch eine Sekunde und dann killdie strace.

Beispiel

Beim Parsen dieser Ausgabe werden Sie feststellen, dass eine Datei als geöffnet O_WRONLYwird, um in eine Datei zu schreiben.

open("/tmp/sh-thd-4137571604", O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600) = 3

Oben sehen wir, in welche Datei Ihre Befehlssequenz schreibt.

slm
quelle
1
Nicht "die Dateideskriptoren erstellen" (das macht keinen Sinn). So erstellen Sie die Datei . Es ist nicht so, readdass eine Datei zum Schreiben geöffnet wird (das wäre albern), es ist <<<.
Gilles 'SO - hör auf böse zu sein'
@ Gilles - danke, ich habe nicht ganz verstanden, was es mir sagte. Aufgeräumt die A.
slm
Vielen Dank! Eine sehr schöne Technik, die mir in Zukunft bei ähnlichen Problemen sogar mehrmals helfen könnte. Eines macht mir jedoch Sorgen, und das ist die Tatsache, dass /tmpes sich um einen fest codierten Pfad handelt. Und wahrscheinlich haben Sie es erraten, /tmp IST schon da, aber auch schreibgeschützt! Und da ich bei der Arbeit an dieser Wiederherstellungskonsole in meinem Live- Dateisystem angemeldet bin, möchte ich mich dort nicht durch Symlinking oder was auch immer (nicht einmal in dieser Konsole) einmischen.
Syntaxfehler
3

Ich finde Positionsparameter für diese Art von Aufgabe sehr nützlich. Es ist im Allgemeinen auch für alle Shells portierbar und kostet weder Gabeln noch temporäre Dateien.

$ HostFull=main:mid:sub    
$ oldIFS=$IFS; IFS=:; set -- $HostFull; IFS=$oldIFS
$ echo $1
main
$ echo $2
mid
$ echo $3
sub
David Sainty
quelle
Ein guter Ansatz! Vielen Dank. Außerdem gefällt es mir, dass keine externen Tools erforderlich sind (die normalerweise in diesen eingeschränkten Umgebungen ohnehin nicht zu finden sind). Das einzige , was kann einige Probleme verursachen ist die $1, $2, $3Material: dass in einem Skript erinnern, dies wird in der Regel für ein Argument an das Skript übergeben steht sich . - Und wenn wir schon dabei sind: Wenn IFS ein Leerzeichen sein soll, reicht * IFS = * in dieser Syntax nicht aus; Sie müssen IFS = '' explizit angeben .
Syntaxfehler