Geben Sie die Eingabe automatisch in die Befehlszeile ein


142

Ich führe ein Skript aus, das bei jeder Operation die Eingabe von 'y' anfordert. Ich suche nach einer Lösung $ ./script < echo 'yyyyyyyyyyyyyy', um alle meine Eingaben auf einmal zu übermitteln.


Manchmal -ffunktioniert die Option auch mit bestimmten Befehlen.
iammilind

Antworten:


258

Es gibt einen speziell für diesen Fall erstellten Befehl: yes

$ yes | ./script

Damit verbinden Sie den Ausgang von yesmit dem Eingang von ./script. Wenn ./scriptnach Benutzereingaben gefragt wird, wird stattdessen die Ausgabe von abgerufen yes. Die Ausgabe von yesist ein endloser Strom von ygefolgt von einer neuen Zeile. Also im Grunde, als ob der Benutzer yfür jede Frage von eingibt ./script.

Wenn Sie nstatt yes ( y) no ( ) sagen möchten, können Sie dies folgendermaßen tun:

$ yes n | ./script

Beachten Sie, dass einige Tools die Option haben, immer yesals Antwort zu fungieren . Siehe hier zum Beispiel: Umgehen der Ja / Nein-Aufforderung in 'apt-get upgrade'


Andere Eingabemethoden:

Wenn Sie genau wissen, wie viele von yIhrem Skript erwartet werden, können Sie dies folgendermaßen tun:

$ printf 'y\ny\ny\n' | ./script

Die Zeilenumbrüche ( \n) sind die Eingabetasten.

Verwenden Sie printfanstelle von yes, um die Eingabe feiner zu steuern:

$ printf 'yes\nno\nmaybe\n' | ./script

Beachten Sie, dass der Benutzer in einigen seltenen Fällen nicht die Eingabetaste nach dem Zeichen drücken muss. in diesem Fall lassen Sie die Zeilenumbrüche weg:

$ printf 'yyy' | ./script

Der Vollständigkeit halber können Sie hier auch ein Dokument verwenden :

$ ./script << EOF
y
y
y
EOF

Oder wenn Ihre Shell einen Here-String unterstützt :

$ ./script <<< "y
y
y
"

Oder Sie können eine Datei mit einer Eingabe pro Zeile erstellen:

$ ./script < inputfile

Wenn der Befehl ausreichend komplex ist und die oben genannten Methoden nicht mehr ausreichen, können Sie expect verwenden .

Hier ist ein Beispiel für ein supereinfaches Expect-Skript:

spawn ./script
expect "are you sure?"
send "yes\r"
expect "are you really sure?"
send "YES!\r"
expect eof

Technischer Nitpick:

Der hypothetische Befehlsaufruf, den Sie in Ihrer Frage angegeben haben, funktioniert nicht:

$ ./script < echo 'yyyyyyyyyyyyyy'
bash: echo: No such file or directory

Dies liegt daran, dass die Shell-Grammatik einen Umleitungsoperator an einer beliebigen Stelle in der Befehlszeile zulässt. Für die Shell ist Ihre hypothetische Befehlszeile dieselbe wie die folgende:

$ ./script 'yyyyyyyyyyyyyy' < echo
bash: echo: No such file or directory

Das heißt, es ./scriptwird mit dem Argument aufgerufen 'yyyyyyyyyyyyyy'und die stdin wird von einer Datei mit dem Namen eingegeben echo. Und bash beschwert sich, da die Datei nicht existiert.


1
Ich bekomme eine cannot enable tty mode on non tty input. Würdest du einen Workaround dafür kennen?
Bmpasini

Wenn ich den printfTrick mit einer runDatei versuche , deren Installation ich automatisieren muss, erhalte ich lediglich eine Fehlermeldung. Warning: Tried to connect to session manager, None of the authentication protocols specified are supportedDas Skript wird in einem neuen Terminal geöffnet und fordert mich auf, meine Eingaben wie gewohnt manuell einzugeben. Dies geschieht übrigens unter Debian. Irgendwelche Vorschläge?
DavidB

brauche mehr Details. zu groß für Kommentare. Bitte stellen Sie eine neue Frage mit allen Details. Hier können Sie einen Link setzen.
Lesmana

Nichts funktioniert mit "Vagrant Destroy" auf Centos
Drew

Geil einfach! Funktioniert auf dem Google Cloud Beta SQL-Datenimport! Sehr geschätzt!
G_Style

11

Verwenden Sie den Befehl yes:

yes | script

Auszug aus der Manpage:

NAME
       yes - output a string repeatedly until killed

SYNOPSIS
       yes [STRING]...
       yes OPTION

DESCRIPTION
       Repeatedly output a line with all specified STRING(s), or 'y'.

9

Einige Dinge ( apt-getzum Beispiel) akzeptieren spezielle Flags, um im unbeaufsichtigten Modus ausgeführt zu werden (und akzeptieren Standardeinstellungen). In diesem apt-getFall übergeben Sie einfach eine -yFlagge. Dies hängt jedoch vollständig von Ihrem Skript ab.

Wenn Sie kompliziertere Dinge benötigen, können Sie Ihr Skript in ein Expect-Skript einbinden. Mit expect können Sie Ausgaben lesen und Eingaben senden, sodass Sie ziemlich komplizierte Dinge tun können, die andere Skripte nicht zulassen würden. Hier ist eines der Beispiele auf der Wikipedia-Seite :

# Assume $remote_server, $my_user_id, $my_password, and $my_command were read in earlier
# in the script.
# Open a telnet session to a remote server, and wait for a username prompt.
spawn telnet $remote_server
expect "username:"
# Send the username, and then wait for a password prompt.
send "$my_user_id\r"
expect "password:"
# Send the password, and then wait for a shell prompt.
send "$my_password\r"
expect "%"
# Send the prebuilt command, and then wait for another shell prompt.
send "$my_command\r"
expect "%"
# Capture the results of the command into a variable. This can be displayed, or written to disk.
set results $expect_out(buffer)
# Exit the telnet session, and wait for a special end-of-file character.
send "exit\r"
expect eof

Dies kann nicht mit einem .shShell-Skript verwendet werden, oder? Oder gibt es einen Weg?
Shayan

7

Im Shell-Skript können Sie auch den folgenden Trick von Spawn, Expect und Send verwenden

spawn script.sh
expect "Are you sure you want to continue connecting (yes/no)?"
send "yes"

Im obigen Szenario müssen Sie jedoch den Ausdruck angeben, den Sie erwarten, während Sie das Skript ausführen. Weitere Beispiele finden Sie unter folgendem Link

Erwarten Sie in Bash


2

Okay, dies ist möglicherweise keine sehr elegante Lösung, aber wenn Sie Ihre Optionen in eine separate Datei schreiben und sie dann als Eingabe an das Skript übergeben, funktioniert dies ebenfalls. Wenn Sie also eine neue Datei mit all Ihren Optionen erstellen (nennen Sie diese Datei 'options.in'), können Sie Ihr Skript ganz einfach ausführen ./script.sh < options.inund verschiedene Optionsdateien nach Bedarf bearbeiten / erstellen.


Wie soll ich die options.inDatei schreiben ? Kannst du ein Beispiel geben?
Shayan

0

Ich habe ein Bash-Skript mit Dialog geschrieben und brauchte dies auch, um automatisch zu funktionieren. Ich habe das getan und es hat wie ein Zauber funktioniert.

# -Wy force signaturewipe (if exists)
echo "y" | sudo lvcreate -W y -n $lvName -L "$lvSize"G /dev/"$svg" >> $nfsUtilLog

-1

Sie können Benutzereingaben für Ihr Skript cataus einer Textdatei bereitstellen , die folgendermaßen an Ihr Skript weitergeleitet wird bash:

cat input.txt | bash your_script.sh

Fügen Sie einfach die gewünschten Benutzereingaben in Ihre input.txt-Datei ein, und wählen Sie die gewünschten Antworten aus - y, n, Ziffern, Zeichenfolgen usw.



@muru Für mich hat die Lösung, die Sie erwähnt haben, nicht funktioniert, deshalb muss ich meine eigene erfinden.
WebComer

Unwahrscheinlich. Sie beide beschreiben dasselbe.
muru

@muru Gleichermaßen ist die Idee, Antworten aus einer Datei zu liefern (was auf verschiedene Arten erfolgen kann), nicht dasselbe, und darüber hinaus wurde eine ganz andere Art und Weise erreicht. Sie sollten es sehen können. Wenn die Lösung, auf die Sie hinweisen, für mich funktionieren würde, werde ich heute nicht meine Zeit damit verbringen, das Rad neu zu erfinden. Sie können jede Arbeit für Sie verwenden.
WebComer

@muru Ich glaube, es gibt einen Unterschied zwischen den beiden, von denen einige in den Antworten beschrieben sind, sagen hier askubuntu.com/questions/172982/… . Für mich zum Beispiel erscheint mein Code, wenn die Ausgabe in eine Datei umgeleitet wird, klarer als ein natürlicher Fluss von links nach rechts. Schließlich regt ein Downvoting von gut funktionierenden Lösungen wie Ihnen nicht dazu an, ihre Lösungen hier mitzuteilen. Ich glaube, das reicht aus, um Abstimmungen zu beseitigen.
WebComer
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.