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.


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.


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'.

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

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


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.


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

-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.



@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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.