Automatycznie wprowadź dane wejściowe w wierszu polecenia

141

Korzystam ze skryptu, który żąda wpisania „y” przy każdej operacji, szukam rozwiązania takiego jak $ ./script < echo 'yyyyyyyyyyyyyy'przekazywanie wszystkich danych wejściowych za jednym razem.

NewMrd
źródło
Czasami -fopcja działa dobrze z niektórymi poleceniami.
iammilind

Odpowiedzi:

257

Istnieje specjalnie utworzone polecenie dla tego przypadku: yes

$ yes | ./script

To robi to podłączyć wyjście yesdo wejścia ./script. Więc kiedy ./scriptpoprosi o dane wejściowe użytkownika, zamiast tego otrzyma wynik yes. Wynikiem yesjest niekończący się strumień, ypo którym następuje nowa linia. Zasadniczo tak, jakby użytkownik wpisał ykażde pytanie ./script.

Jeśli chcesz powiedzieć nie ( n) zamiast tak ( y), możesz to zrobić w następujący sposób:

$ yes n | ./script

Pamiętaj, że niektóre narzędzia mają opcję, aby zawsze przyjmować yesjako odpowiedź. Zobacz tutaj na przykład: Ominięcie monitu o tak / nie w 'apt-get upgrade'


Inne metody wprowadzania danych wejściowych:

Jeśli wiesz dokładnie, ile yoczekuje Twój skrypt, możesz to zrobić w następujący sposób:

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

Nowe linie ( \n) to klawisze Enter.

Używanie printfzamiast yesciebie ma bardziej precyzyjną kontrolę wejścia:

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

Zauważ, że w niektórych rzadkich przypadkach polecenie nie wymaga od użytkownika naciśnięcia klawisza Enter po znaku. w takim przypadku pozostaw nowe linie:

$ printf 'yyy' | ./script

Dla zachowania kompletności możesz również skorzystać z dokumentu tutaj :

$ ./script << EOF
y
y
y
EOF

Lub jeśli twoja powłoka obsługuje to ciąg tutaj :

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

Lub możesz utworzyć plik z jednym wejściem w wierszu:

$ ./script < inputfile

Jeśli polecenie jest wystarczająco złożone, a powyższe metody już nie wystarczają, możesz użyć metody expect .

Oto przykład bardzo prostego skryptu oczekiwanego:

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

Techniczny nitpick:

Hipotetyczne wywołanie polecenia podane w pytaniu nie działa:

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

Jest tak, ponieważ gramatyka powłoki pozwala operatorowi przekierowania w dowolnym miejscu wiersza poleceń. Jeśli chodzi o powłokę, twoja hipotetyczna linia poleceń jest taka sama jak ta linia:

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

Oznacza to, ./scriptże zostanie wywołany z argumentem, 'yyyyyyyyyyyyyy'a standardowe wejście otrzyma dane wejściowe z pliku o nazwie echo. I bash narzeka, ponieważ plik nie istnieje.

lesmana
źródło
1
Dostaję cannot enable tty mode on non tty input. Czy znasz to obejście?
bmpasini,
Kiedy próbuję printfpodstępu z runplikiem, który muszę zautomatyzować proces instalacji, wszystko, co się dzieje, to pojawia się komunikat o błędzie Warning: Tried to connect to session manager, None of the authentication protocols specified are supported, a skrypt otwiera się w nowym terminalu i prosi mnie o ręczne wprowadzenie danych jak zwykle. Nawiasem mówiąc, dzieje się to na Debianie. Jakieś sugestie?
DavidB
potrzebuję więcej szczegółów. za duży na komentarze. proszę zadać nowe pytanie ze wszystkimi szczegółami. możesz umieścić link tutaj.
lesmana
nic nie działa z „włóczęgą niszczą” na centos
Drew
Wicked easy! Działa na import danych Google Cloud Beta SQL! Bardzo mile widziane!
G_Style
11

Użyj polecenia yes:

yes | script

Fragment strony man:

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'.
Peter W. Osel
źródło
9

Niektóre rzeczy ( apt-getna przykład) akceptują specjalne flagi do działania w trybie cichym (i akceptują wartości domyślne). W takim apt-getprzypadku po prostu podajesz mu -yflagę. Zależy to jednak całkowicie od twojego skryptu.

Jeśli potrzebujesz bardziej skomplikowanych rzeczy, możesz owinąć swój skrypt skryptem oczekiwanym. Oczekiwanie pozwala odczytać dane wyjściowe i wysłać dane wejściowe, dzięki czemu można wykonywać dość skomplikowane czynności, na które nie pozwalałoby inne skrypty. Oto jeden z przykładów ze strony Wikipedii :

# 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
Oli
źródło
Tego nie można użyć ze .shskryptem powłoki, prawda? Czy jest jakiś sposób?
Shayan
7

W skrypcie powłoki możesz także użyć następującej sztuczki spawnowania, oczekiwania i wysyłania

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

Jednak w powyższym scenariuszu będziesz musiał podać frazę, której oczekujesz podczas wykonywania skryptu, aby uzyskać więcej przykładów, przejdź do następującego linku

Spodziewaj się w Bash

Tarun
źródło
2

Ok, to może nie być bardzo eleganckie rozwiązanie, ale jeśli napiszesz opcje w osobnym pliku, a następnie przekażesz je jako dane wejściowe do skryptu, to również zadziała. Jeśli więc utworzysz nowy plik ze wszystkimi opcjami (nazwij ten plik jako „options.in”), możesz łatwo uruchomić skrypt ./script.sh < options.ini edytować / tworzyć różne pliki opcji odpowiednio.

Sidha
źródło
Jak mam zapisać options.inplik? Czy możesz podać przykład?
Shayan
0

Pisałem skrypt bash w Dialogu i potrzebowałem, aby stało się to również automatycznie. Zrobiłem to i zadziałało jak urok.

# -Wy force signaturewipe (if exists)
echo "y" | sudo lvcreate -W y -n $lvName -L "$lvSize"G /dev/"$svg" >> $nfsUtilLog
Benjamin West
źródło
-1

Możesz podać dane wejściowe użytkownika do skryptu za catpomocą pliku tekstowego przesyłanego strumieniowo do skryptu w bashnastępujący sposób:

cat input.txt | bash your_script.sh

Po prostu umieść żądane dane wejściowe użytkownika w pliku input.txt, niezależnie od potrzebnych odpowiedzi - y, n, cyfry, ciągi itp.

WebComer
źródło
@muru Dla mnie wspomniane rozwiązanie nie zadziałało, więc muszę wymyślić własne.
WebComer,
Mało prawdopodobne. Oboje opisujcie to samo.
muru
@muru Podobnie pomysł dostarczenia odpowiedzi z pliku (co można zrobić na kilka sposobów) nie jest tym samym, a ponadto osiągnął całkiem inny sposób. Powinieneś być w stanie to zobaczyć. Jeśli wskazane przez Ciebie rozwiązanie zadziałałoby dla mnie, nie spędzę dziś czasu na nowo opracowując koło. Możesz użyć dowolnej pracy dla siebie.
WebComer
@muru wierzę, że istnieje różnica między tymi dwoma, z których niektóre opisano w odpowiedzi tutaj powiedzieć askubuntu.com/questions/172982/... . Dla mnie, na przykład, mój kod, jeśli dane wyjściowe są przekierowane do pliku, wydaje się wyraźniejszy jako naturalny przepływ od lewej do prawej. W końcu przegłosowanie dobrze działających rozwiązań takich jak Ty nie zachęca ludzi do dzielenia się swoimi rozwiązaniami tutaj. Uważam, że powiedziane to wystarczy, aby usunąć głosowanie z dołu.
WebComer