Ich habe ein lang laufendes Bash-Skript, das ich nicht als Root ausführen möchte, das jedoch regelmäßig Root-Zugriff benötigt. Ich habe dieses Problem gelöst, indem ich den Benutzer nach dem Root-Passwort gefragt habe
sudo -v
und dann habe ich einen Prozess hinterlegt, der den Sudo-Timer mit schleifen und zurücksetzen würde
sudo -n true
Ich bekam dann seltsame Probleme bei der Verwendung read
im Hauptprozess. Hier ist ein minimales Skript, das dieses Problem zeigt. Wenn Sie es ausführen und vor dem sudo -n true
Ausführen nichts eingeben, erhält der Lesevorgang einread error: 0: Resource temporarily unavailable
#!/usr/bin/env bash
sudo -v # ask user for password
sleep 1 && sudo -n true & # background a process to reset sudo
printf "Reading text: "
read -n 1 TEXT
echo "Read text: $TEXT"
Ich konnte dieses Verhalten mit keinem anderen Befehl außer replizieren sudo
. Wie kann ich sudo -n true
im Hintergrund laufen, ohne mich einzumischen read
?
Bearbeiten:
Ich bekomme dieses Problem nur unter Ubuntu, nicht unter MacOS.
sudo -v
erneut verwendensudo -n true
?Antworten:
Ich bekomme das gleiche Verhalten mit:
sudo
wird geöffnet/dev/tty
, um die aktuelle Vordergrundprozessgruppe abzufragen, wodurch derread()
vonread
bashs ausgeführte Systemaufruf mit EAGAIN mit dem Linux-Kernel 4.15.0-45-generic und 4.18.0-14-generic von Ubuntu 18.04 zurückgegeben wird, wodurch zumindest dasread
Dienstprogramm zurückgegeben wird mit diesem Fehler.Dies scheint auf einen Fehler in neueren Versionen der Ubuntu-Varianten des Linux-Kernels zurückzuführen zu sein . Ich kann es weder unter Solaris noch unter FreeBSD oder in einer Linux-Version unter Debian reproduzieren (obwohl ich es reproduzieren kann, wenn ich Debian auf Ubuntus 4.18-Kernel starte).
https://bugs.launchpad.net/ubuntu/+source/linux-signed-hwe/+bug/1815021 scheint eine weitere Manifestation dieses Fehlers zu sein.
Dies wird durch https://lkml.org/lkml/2018/11/1/663 eingeführt, das Ubuntu mindestens auf seine Kernel 4.15 und 4.18 zurückportiert hat. Aber Ubuntu hatte bis vor 2 Stunden keine weitere Änderung zurückportiert, die eine durch diesen Patch eingeführte Regression behebt .
4.18.0-15-generic ist jetzt in den Ubuntu-Repositories gelandet und behebt das Problem. Ich nehme an, der für 4.15 wird in Kürze folgen.
ksh93
hat nicht das Problem für denselben Code, den derread
integrierte Code zuerst verwendetselect()
, um auf die Eingabe zu warten, undselect()
kehrt nicht zurück, wenn der andere Prozess geöffnet wird/dev/tty
.Hier können Sie also
ksh93
anstellebash
oder warten auf den festen Kernel oder kehren zu 4.15.0-43 zurück, bis 4.15.0-46 veröffentlicht wird.Alternativ können Sie
zsh
die integrierte Unterstützung für das Ändern von UIDs (über die speziellen Variablen EUID / UID / USERNAME) verwenden, sofern Sie das Skript starten,root
damit Sie es nichtsudo
innerhalb des Skripts ausführen müssen (es ist möglicherweise auch gefährlich, die Lebensdauer von zu verlängern das Sudo-Token länger als vom Benutzer erwartet).quelle
/dev/tty
dazu führen kann, dass aread
zurückkehrtEAGAIN
. Sicherlich nicht wegen einer SIGCHLD mit CLD_STOPPED (selbst verursacht durch eine SIGTTIN)? Gibt es einen bekannten Fehler, der das erklärt?strace
, es ist auf jeden Fall dieopen()
auf/dev/tty
den auslöst , dieread()
mit EAGAIN zurückzukehren. Auf diesem System kann ich mit jeder Shell oder jedem Dienstprogramm reproduzieren, die / dasread()
auf dem Endgerät ausgeführt wird.EAGAIN
Lesevorgang durchzuführen, besteht darin, O_NONBLOCK für dasselbe Dateiobjekt festzulegen. Beim Öffnen/dev/tty
wird jedoch nicht dasselbe Dateiobjekt wie z./dev/pts/4
. zBsleep 1 && perl -MFcntl=F_SETFL,F_GETFL,O_NONBLOCK -e 'fcntl STDIN, F_SETFL, fcntl(STDIN, F_GETFL, 0) | O_NONBLOCK' & read foo
führt dies nicht dazu, dass der Lesevorgang mit EAGAIN fehlschlägt, wenn die Eingabe von Perl/dev/tty
stattdessen umgeleitet wird.bash -c 'sleep 1 && true < /dev/tty & read var'
4.18 unter Ubuntu bekomme, aber nicht unter Debian. Es kann auch an den sysctl-Optionen liegen. Ich werde versuchen einzugrenzen, was es unter Ubuntu verursacht. In jedem Fall soll EAGAIN zwar von nicht blockierenden Beschreibungen offener Dateien zurückgegeben werden, dies ist hier jedoch nicht der Fall. Es sieht nach einem bestimmten Verhalten des pty-Treibers mit diesen Kerneln aus.