Manchmal arbeite ich an einer neuen (Ubuntu-)Box, gebe Folgendes ein git
und werde benachrichtigt:
The program 'git' is currently not installed. You can install it by typing:
apt-get install git-core
Wenn das passiert, weiß ich, dass ich die letzte Zeile abrufen kann, indem ich etwas wie Folgendes mache:
!! 2>&1 | tail -n 1
Aber wie könnte ich das Ergebnis davon ( apt-get install git-core
) am einfachsten ausführen?
Mir ist klar, dass ich das tun könnte
`!! 2>&1 | tail -n 1`
aber gibt es auch eine Möglichkeit, die Ausgabe tatsächlich weiterzuleiten und auszuführen? Das scheint nicht zu funktionieren:
!! 2>&1 | tail -n 1 | sh
Außerdem ist das 2>&1
Teil etwas umständlich, daher würde mich interessieren, ob es auch dafür einen einfacheren Weg gibt.
Bearbeiten
Es wäre auch akzeptabel, dies irgendwie in einer Variable zu speichern und dann die Variable auszuführen:
!! 2>&1 | tail -n 1 | (store as $mycmd)
$mycmd
Ich bin mir aber auch nicht sicher, ob ich eine Möglichkeit kenne, eine Weiterleitung stdout
in eine Variable durchzuführen, zumindest nicht, wenn sich die Variable auf der rechten Seite des Befehls befindet.
Antwort1
Wenn Sie einen Befehl eingeben, der in Ihrem System nicht vorhanden ist, führt Bash die Funktion aus command_not_found_handle()
. In dieser Funktion wird ein Skript aufgerufen /usr/lib/command-not-found
, das Nachrichten druckt.
Ubuntu 12.04
Meine erste Vermutung war, den Quelltext dieses Skripts zu ändern, um stdout
stattdessen Nachrichten an auszugeben stderr
, aber als ich den Quelltext des Skripts las, stellte ich fest, dass man es so konfigurieren kann, dass man nur gefragt wird, ob man ein fehlendes Paket installieren möchte.
Wenn Sie Variablen exportieren, COMMAND_NOT_FOUND_INSTALL_PROMPT
werden Sie aufgefordert, fehlende Pakete zu installieren:
pbm@ubuntu:~$ git
The program 'git' is currently not installed. You can install it by typing:
sudo apt-get install git
pbm@ubuntu:~$ export COMMAND_NOT_FOUND_INSTALL_PROMPT=""
pbm@ubuntu:~$ git
The program 'git' is currently not installed. You can install it by typing:
sudo apt-get install git
Do you want to install it? (N/y)y
sudo apt-get install git
[sudo] password for pbm:
Ältere Versionen von Ubuntu
Leider gibt es keine COMMAND_NOT_FOUND_INSTALL_PROMPT
, daher kann ich ein paar andere Optionen finden:
1) Installieren Sie das Paket von 12.04 – das sollte nicht das Problem sein – es sind nur wenige Skripte in Python, also sollte es funktionieren (ungetestet!).
2) Wechseln Sie stderr
zu stdout
. Bearbeiten Sie dazu die Datei /usr/lib/python2.7/dist-packages/CommandNotFound/CommandNotFound.py
und wechseln Sie in den Zeilen 237 und 240 stderr
zu .stdout
Danach können Sie es folgendermaßen verwenden:
pbm@ubuntu:~$ git
The program 'git' is currently not installed. You can install it by typing:
sudo apt-get install git
pbm@ubuntu:~$ `git`
//Installation begins
Wenn Sie in den Zeilen 237 und 240 -y
eine Option zum Befehl hinzufügen, können Sie auch die Syntax verwenden .apt-get
!! | sh
3) Sie können dieses Skript ab Zeile 242 auch folgendermaßen modifizieren:
print >> sys.stderr, _("You can install it by typing:")
f = open("%s/.install-missing" % os.path.expanduser('~'),'w')
print >> sys.stderr, "sudo apt-get install %s" % packages[0][0]
print >> f, "sudo apt-get install %s" % packages[0][0]
f.close()
Auf diese Weise erhalten Sie Ihren Befehl in der Datei ~/.install-missing
, sodass Sie einen Alias erstellen können:
alias im="chmod +x ~/.install-missing; ~/.install-missing"
Wenn Sie anrufen, im
wird das Paket installiert.
Antwort2
Mit diesen Angaben waren Sie auf dem richtigen Weg:
!! 2>&1 | tail -n 1 | sh
...aber Ihnen fehlt eine Option, umSch. Halten:
!! 2>&1 | tail -n 1 | sh -s
Und da Sie zum Ausführen von apt-get wahrscheinlich Root-Zugriff benötigen, beachten Sie Folgendes:
!! 2>&1 | tail -n 1 | sudo sh -s
Antwort3
Sie können etwa Folgendes tun:
!! 2>&1 | tail -n 1 > /tmp/cmd; bash /tmp/cmd; rm /tmp/cmd
Interaktive Programme scheinen mit Piping nicht gut zu funktionieren, da eine Eingabe erwartet wird, in diesem Fall „Y“, der Stdin-Dateideskriptor jedoch geschlossen wird, sobald der erste Befehl abgeschlossen ist.
Antwort4
Sie können eine Variable eval
und, glaube ich, eine Befehlsersetzung verwenden (obwohl ich nicht sicher bin, wie sicher das alles wäre):
TEST_VAR=$(!! 2>&1 | tail -n 1); eval $TEST_VAR
Ich bin bereit, mich mit dem oben Gesagten als falsch erweisen zu lassen. Ich teste dies auf einer Red Hat-Maschine mit einem echo
Befehl anstelle der automatischen Bash-Vervollständigung, aber das Prinzip sollte dasselbe sein.
Letztendlich wäre es schneller, einfach „aptitude install git...“ einzugeben.