Pseudopliki dla danych tymczasowych


98

Często chcę podawać stosunkowo krótkie dane łańcuchowe (choć może to być kilka wierszy) do programów wiersza poleceń, które przyjmują tylko dane wejściowe z plików (np. Wdiff) w powtarzający się sposób. Jasne, że mogę utworzyć jeden lub więcej plików tymczasowych, zapisać tam ciąg i uruchomić polecenie z nazwą pliku jako parametrem. Ale wydaje mi się, że ta procedura byłaby wysoce nieefektywna, jeśli dane są faktycznie zapisywane na dysk, a także może uszkodzić dysk bardziej niż to konieczne, jeśli powtórzę tę procedurę wiele razy, np. Jeśli chcę podać pojedyncze wiersze długiego tekstu pliki do wdiff. Czy istnieje zalecany sposób na obejście tego, na przykład za pomocą pseudoplików, takich jak potoki, do tymczasowego przechowywania danych bez faktycznego zapisywania ich na dysku (lub zapisywania tylko wtedy, gdy przekracza on długość krytyczną). Zauważ, że wdiff bierze dwa argumenty i,wdiff <"text".


Czy można to rozwiązać za pomocą xargs?
NN

Nie wiem, ale nie byłoby dla mnie oczywiste jak. O ile rozumiem xargs, wprowadziłbym wiersze wejściowe z argumentów ciągu pliku dla polecenia. Ale potrzebuję czegoś przeciwnego.
highsciguy

@rahmu Spojrzałem, ale myślę, że problem jest nieco inny. Przynajmniej nie rozumiem, w jaki sposób odpowiedzi mogłyby pomóc. Przyjęta odpowiedź na prawidłowe tworzenie plików tymczasowych jest zasadniczo tym, czego nie chciałbym uniknąć, jeśli nie, istnieje pewien rodzaj buforowania, który faktycznie uniemożliwia zapisywanie plików. Mam ograniczone zrozumienie działania plików tymczasowych!
highsciguy

Co jest nie tak z echo $data_are_here | dumb_program?
vonbrand,

1
Obsługuje tylko jeden plik wejściowy i nie wszystkie programy czytają ze standardowego wejścia.
highsciguy

Odpowiedzi:


55

Użyj nazwanego potoku . Tytułem ilustracji:

mkfifo fifo
echo -e "hello world\nnext line\nline 3" > fifo

-eMówi echo poprawnie zinterpretować ucieczkę nowej linii ( \n). Spowoduje to zablokowanie, tzn. Twoja powłoka zawiesi się, dopóki coś nie odczyta danych z potoku.

Otwórz kolejną powłokę gdzieś w tym samym katalogu:

cat fifo

Przeczytasz echo, które uwolni drugą powłokę. Chociaż potok istnieje jako węzeł pliku na dysku, dane, które przez niego przechodzą, nie istnieją; wszystko odbywa się w pamięci. Możesz włączyć &echo w tle ( ).

Potok ma bufor 64k (na Linuksie) i, podobnie jak gniazdo, zablokuje pisarz po zapełnieniu, więc nie stracisz danych, dopóki nie zabijesz przedwcześnie pisarza.


Ok, dzięki, działa to również z dwoma nazwanymi potokami i wdiff. Ale pomyślałem, aby zrozumieć, że dla potoku jako bufora dostępna jest pewna (mała) ilość pamięci. Co się stanie, jeśli przekroczę rozmiar bufora?
highsciguy

Dodałem ostatni akapit na ten temat.
goldilocks

3
/tmpjest skonfigurowany w większości dystrybucji, aby używać tmpfssystemu plików, który jest w pamięci RAM. Kiedy piszesz w /tmpnim plik , przechodzi on bezpośrednio do pamięci RAM, co stanowi dobrą odpowiedź na pliki półelastyczne, do których trzeba szybko uzyskać dostęp i wielokrotnie przepisywać.

129

W Bash możesz użyć command1 <( command0 )składni przekierowania, która przekierowuje standardowe command0wyjście i przekazuje je do pliku, command1który przyjmuje nazwę pliku jako argument wiersza poleceń. Nazywa się to substytucją procesu .

Niektóre programy, które pobierają argumenty wiersza polecenia z nazwą pliku, tak naprawdę potrzebują prawdziwego pliku o swobodnym dostępie, więc ta technika nie będzie działać dla tych. Działa to jednak dobrze z wdiff:

user@host:/path$ wdiff <( echo hello; echo hello1 ) <( echo hello; echo hello2 )
hello
[-hello1-]
{+hello2+}

W tle tworzy to FIFO, <( )przekazuje polecenie do FIFO i przekazuje deskryptor pliku FIFO jako argument. Aby zobaczyć, co się dzieje, spróbuj użyć go echodo wypisania argumentu, nie robiąc nic z tym:

user@host:/path$ echo <( echo hello )
/dev/fd/63

Tworzenie nazwanego potoku jest bardziej elastyczne (jeśli chcesz napisać skomplikowaną logikę przekierowań przy użyciu wielu procesów), ale dla wielu celów to wystarczy i jest oczywiście łatwiejsze w użyciu.

Istnieje również >( )składnia, kiedy chcesz użyć go jako danych wyjściowych, np

$ someprogram --logfile >( gzip > out.log.gz )

Zobacz także ściągawki przekierowań Bash dla powiązanych technik.


To nie jest obsługiwane w KSH
chanchal1987

5
ksh wynalazł to. Używasz wariantu ksh, który go nie obsługuje
Neil McGuigan,

2
Niektóre programy, które pobierają argumenty wiersza polecenia z nazwą pliku, tak naprawdę potrzebują prawdziwego pliku o swobodnym dostępie, więc ta technika nie będzie działać dla tych. Co robisz w tych przypadkach? Na przykład ssh -F <(vagrant ssh-config) defaultbyłoby naprawdę miło, ale niestety.
Sukima

10

wdiff jest szczególnym przypadkiem, ponieważ wymaga 2 argumentów nazwy pliku, ale dla wszystkich poleceń, które wymagają tylko 1 argumentu i które uparcie nie przyjmują niczego oprócz argumentu nazwy pliku, istnieją 2 opcje:

  • Nazwa pliku „-” (czyli znak minus) działa przez około 1/2 czasu. Wygląda na to, że zależy od danego polecenia i tego, czy twórca polecenia przechwytuje tę sprawę i obsługuje ją zgodnie z oczekiwaniami. na przykład

    $> ls | kot -

  • Istnieje plik psuedo o nazwie / dev / stdin, który istnieje w systemie Linux i można go użyć, jeśli nazwa pliku jest absolutnie wymagana przez polecenie. Jest to bardziej prawdopodobne, że zadziała, ponieważ nie wymaga specjalnej obsługi nazw plików z polecenia. Jeśli fifo działa lub działa metoda podstawiania procesu bash , to powinno to również działać i nie jest specyficzne dla powłoki. na przykład

    $> ls | cat / dev / stdin


1
mniej i openssl jak / dev / stdin zamiast / dev / fd / NUM :-)
węgorz ghEEz 30.04.2016
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.