Zastanawiam się, kiedy powinniśmy korzystać z rurociągów, a kiedy nie.
Powiedzmy na przykład, aby zabić pewien proces, który obsługuje pliki pdf, następujące działania nie będą działać przy użyciu potoku:
ps aux | grep pdf | awk '{print $2}'|kill
Zamiast tego możemy to zrobić tylko na następujące sposoby:
kill $(ps aux| grep pdf| awk '{print $2}')
lub
ps aux | grep pdf | awk '{print $2}'| xargs kill
Według man bash
(wersji 4.1.2
):
The standard output of command is connected via a pipe to the standard input of command2.
Dla powyższego scenariusza:
- stdin
grep
jest stdoutps
. To działa. - stdin
awk
jest stdoutgrep
. To działa. - stdin
kill
jest stdoutawk
. To nie działa.
Stdin następującego polecenia zawsze pobiera dane wejściowe ze standardowego wejścia poprzedniego polecenia.
- Dlaczego to nie działa z
kill
lubrm
? - Co to jest różnie
kill
,rm
wejście zgrep
,awk
wejście? - Czy są jakieś zasady?
pgrep
,pkill
ikillall
poleceń.pgrep
a reszta może to doskonale osiągnąć :)Odpowiedzi:
Istnieją dwa typowe sposoby dostarczania danych wejściowych do programów:
kill
używa tylko argumentów wiersza poleceń. Nie czyta ze STDIN. Programy takie jakgrep
iawk
czytane ze STDIN (jeśli nie podano nazw plików jako argumentów wiersza poleceń) i przetwarzają dane zgodnie z ich argumentami wiersza poleceń (wzorzec, instrukcje, flagi, ...).Można tylko potokować do STDIN innych procesów, a nie do argumentów wiersza poleceń.
Powszechną zasadą jest, że programy używają STDIN do przetwarzania dowolnej ilości danych. Wszystkie dodatkowe parametry wejściowe lub, jeśli zwykle jest ich niewiele, przekazywane są przez argumenty wiersza poleceń. Jeśli wiersz poleceń może być bardzo długi, na przykład w przypadku długich
awk
tekstów programów, często istnieje możliwość odczytania ich z dodatkowych plików programu (-f
opcjaawk
).Aby użyć STDOUT programów jako argumentów wiersza poleceń, użyj
$(...)
lub w przypadku dużej ilości danychxargs
.find
można to również bezpośrednio z-exec ... {} +
.Dla kompletności: Aby zapisać argumenty wiersza poleceń do STDOUT, użyj
echo
.źródło
gzip
w SYNOPSIS nie powiedziano, że musi on przyjmować NAZWĘ PLIKU jako dane wejściowe. Szukam, czy istnieje bardziej systematyczny sposób, aby to ustalić.xargs
pozwoli ci dokładnie „sprowadzać argumentów do wiersza poleceń”?xargs
. W razie potrzeby wywołuje polecenie więcej niż jeden raz (rozmiar wiersza polecenia jest ograniczony) i ma wiele innych opcji.To interesujące pytanie, które dotyczy części filozofii Unix / Linux.
Więc jaka jest różnica między programami takimi jak
grep
,sed
,sort
z jednej strony, akill
,rm
,ls
z drugiej strony? Widzę dwa aspekty.Filtr aspekt
Pierwszy rodzaj programów nazywa się również filtrami . Pobierają dane wejściowe z pliku lub ze STDIN, modyfikują je i generują dane wyjściowe, głównie do STDOUT. Są przeznaczone do użycia w potoku z innymi programami jako źródłami i miejscami docelowymi.
Drugi rodzaj programów działa na dane wejściowe, ale dane wyjściowe, które dają, często nie są powiązane z danymi wejściowymi.
kill
nie ma wyjścia, gdy działa regularnie, podobnie jak niels
. Po prostu mają wartość zwracaną, aby pokazać sukces. Zwykle nie pobierają danych wejściowych ze STDIN, ale przeważnie przekazują dane wyjściowe do STDOUT.W przypadku takich programów
ls
aspekt filtrowania nie działa tak dobrze. Z pewnością może mieć wejście (ale go nie potrzebuje), a wyjście jest ściśle powiązane z tym wejściem, ale nie działa jako filtr. Jednak w przypadku tego rodzaju programów drugi aspekt nadal działa:Semantyczny aspekt
W przypadku filtrów ich wejście nie ma znaczenia semantycznego . Po prostu odczytują dane, modyfikują dane, dane wyjściowe. Nie ma znaczenia, czy jest to lista wartości liczbowych, niektórych nazw plików czy kodu źródłowego HTML. Znaczenie tych danych jest podane tylko przez kod, który podajesz do filtra: wyrażenie regularne dla
grep
, regułyawk
lub program Perla.W przypadku innych programów, takich jak
kill
lubls
, ich wprowadzanie ma znaczenie , oznaczenie .kill
oczekuje numerów procesów,ls
oczekuje nazw plików lub ścieżek. Nie mogą obsługiwać dowolnych danych i nie są przeznaczone do tego. Wiele z nich nie potrzebuje nawet żadnych danych wejściowych ani parametrówps
. Zwykle nie czytają ze STDIN.Prawdopodobnie można by połączyć te dwa aspekty: Filtr to program, którego dane wejściowe nie mają znaczenia semantycznego dla programu.
Jestem pewien, że gdzieś przeczytałem o tej filozofii, ale w tej chwili nie pamiętam żadnych źródeł, przepraszam. Jeśli ktoś ma jakieś źródła, możesz je edytować.
źródło
Nie ma „zasad” jako takich. Niektóre programy pobierają dane ze STDIN, a niektóre nie. Jeśli program może pobierać dane wejściowe ze STDIN, może być przesyłany potokowo, jeśli nie, nie może.
Zwykle możesz stwierdzić, czy program pobierze dane, myśląc o tym, co robi. Jeśli praca programu jest w jakiś sposób manipulować zawartość z pliku (np
grep
,sed
,awk
etc.), to zwykle trwa wejściowe z stdin. Jeśli jego zadaniem jest manipulowanie sam plik (npmv
,rm
,cp
) lub proces (npkill
,lsof
) lub powrotnej do informacji o czymś (nptop
,find
,ps
), to nie.Innym sposobem myślenia na ten temat jest różnica między argumentami a danymi wejściowymi. Na przykład:
W powyższym poleceniu
mv
nie ma danych wejściowych jako takich. Podano dwa argumenty. Nie wie ani nie obchodzi, co jest w żadnym z plików, po prostu wie, że to są jego argumenty i powinien nimi manipulować.Z drugiej strony
Tutaj
sed
podano dane wejściowe oraz argument. Ponieważ pobiera dane wejściowe, może je odczytać ze STDIN i może być przesyłane potokowo.Staje się bardziej skomplikowane, gdy argumentem może być dane wejściowe. Na przykład
Oto
file
argument, który został podanycat
. Mówiąc ściślej, argumentem jest nazwa plikufile
. Ponieważ jednakcat
jest to program, który manipuluje zawartością plików, jego wejściem jest wszystko, co jest w środkufile
.Można to zilustrować za
strace
pomocą programu, który śledzi wywołania systemowe wykonywane przez procesy. Jeśli uruchomimycat foo
przezstrace
, możemy zobaczyć, że plikfoo
jest otwarty:Pierwszy wiersz powyżej pokazuje, że program
/bin/cat
został wywołany, a jego argumentami byłycat
ifoo
(pierwszym argumentem jest zawsze sam program). Później argumentfoo
został otwarty w trybie tylko do odczytu. Teraz porównaj to zTutaj także
ls
wziął siebie ifoo
jako argumenty. Jednak nie maopen
wywołania, argument nie jest traktowany jako dane wejściowe. Zamiast tegols
wywołujestat
bibliotekę systemową (co nie jest tym samym costat
polecenie), aby uzyskać informacje o plikufoo
.Podsumowując, jeśli uruchomione polecenie odczyta jego dane wejściowe, możesz przesłać do niego potokiem, jeśli nie, nie możesz.
źródło
kill
irm
nie potrzebujesz STDIN.W przypadku
kill
irm
użytkownicy podają swoje niestandardowe informacje jako argument i$(cmd)
pomaga wziąć STDOUTcmd
i przekonwertować go na argument.Dla
grep
iawk
użytkownicy podają argumenty, a ponadtoSTDIN
lub zwykły plik, który będzie przetwarzany przez polecenie.STDIN
można przekazać za pomocą potoku|
lub ręcznie wprowadzając.Przeczytaj instrukcję lub kody źródłowe. A jeśli nie znajdziesz nic, czego potrzebujesz, możesz wykonać prosty, ale może niebezpieczny test:
Wystarczy wprowadzić polecenie, które Cię interesuje, z argumentami, które już rozumiesz, i sprawdź, czy polecenie wstrzymuje się (nic się nie dzieje). Jeśli to wstrzymać, to jest rzeczywiście czeka na STDIN (można spróbować
cat
iecho
zobaczyć różne). Wpisujesz ręcznie,Ctrl-D
a polecenie idzie naprzód (pokazuje wyniki lub błędy) i zwraca. W takim przypadku takie polecenie wymaga STDIN (z podanymi argumentami).To samo polecenie może nie wymagać STDIN w różnych sytuacjach (np.
cat
Czeka na STDIN, alecat file.txt
nie).źródło