Czy powinienem używać nawiasów pojedynczego lub podwójnego kąta do przekierowywania na / dev / null?

18

Większość odpowiedzi tutaj [ 1 ] [ 2 ] [ 3 ] używa pojedynczego nawiasu kątowego, aby przekierowywać do / dev / null, jak poniżej:

command > /dev/null

Ale dołączanie do / dev / null również działa:

command >> /dev/null

Czy oprócz dodatkowego charakteru istnieje jakiś powód, aby tego nie robić? Czy któryś z nich jest „ładniejszy” w stosunku do implementacji / dev / null?

Edit: open (2) podręcznika mówi lseek nazywa się przed każdym zapisie do pliku w trybie dopisywania:

O_APPEND
Plik jest otwierany w trybie dołączania. Przed każdym zapisem (2) przesunięcie pliku jest ustawiane na końcu pliku, tak jak w przypadku lseek (2). Modyfikacja przesunięcia pliku i operacja zapisu są wykonywane jako pojedynczy krok atomowy.

co sprawia, że ​​myślę, że może być niewielka kara za wydajność >>. Ale z drugiej strony obcinanie / dev / null wydaje się niezdefiniowaną operacją według tego dokumentu:

O_TRUNC
Jeśli plik już istnieje i jest zwykłym plikiem, a tryb dostępu umożliwia zapis (tzn. Jest to O_RDWR lub O_WRONLY), zostanie obcięty do długości 0. Jeśli plik jest plikiem FIFO lub plikiem urządzenia końcowego, flaga O_TRUNC jest ignorowana. W przeciwnym razie efekt O_TRUNC nie jest określony.

a specyfikacja POSIX mówi >, że powinien obciąć istniejący plik , ale O_TRUNC jest zdefiniowany dla implementacji plików urządzeń i nie ma słowa o tym, jak / dev / null powinien zareagować na obcięcie .

Czy obcięcie / dev / null faktycznie nie jest określone? I czy wywołania Lseek mają jakiś wpływ na wydajność zapisu?

Morgan
źródło

Odpowiedzi:

27

Z definicji /dev/nullpochłania wszystko, co do niej napisano , więc nie ma znaczenia, czy piszesz w trybie dołączania, czy nie, wszystko jest odrzucane. Ponieważ nie przechowuje danych, naprawdę nie ma się do czego dołączać.

Ostatecznie pisanie > /dev/nulljednym >znakiem jest krótsze .

Jeśli chodzi o edytowany dodatek:

Otwarta (2) strona podręcznika mówi, że lseek jest wywoływany przed każdym zapisem do pliku w trybie dołączania.

Jeśli będziesz czytał uważnie, zobaczysz, że mówi (podkreśl moje):

przesunięcie pliku jest umieszczone na końcu pliku, tak jak w przypadku lseek (2)

Oznacza to, że tak naprawdę (nie musi) wywoływać wywołania lseeksystemowego, a efekt też nie jest dokładnie taki sam: wywoływanie lseek(fd, SEEK_END, 0); write(fd, buf, size);bez O_APPENDnie jest tym samym, co zapis w trybie dołączania, ponieważ przy osobnych wywołaniach inny proces mógłby zapisać do plik pomiędzy wywołaniami systemowymi, niszcząc dołączone dane. W trybie dołączania tak się nie dzieje (z wyjątkiem NFS, który nie obsługuje prawdziwego trybu dołączania ).

Tekst w standardzie nie wspomnieć lseekw tym miejscu, tylko że zapisy powinny iść do końca pliku.

Czy obcięcie / dev / null faktycznie nie jest określone?

Sądząc po pismach, do których się odwołujesz, najwyraźniej jest on zdefiniowany w implementacji. Oznacza to, że każda rozsądna implementacja zrobi to samo, co rury i TTY, a mianowicie nic. Szalona implementacja może zrobić coś innego, a być może obcięcie może oznaczać coś sensownego w przypadku innego pliku urządzenia.

I czy wywołania Lseek mają jakiś wpływ na wydajność zapisu?

Sprawdź to. To jedyny sposób, aby wiedzieć na pewno w danym systemie. Lub przeczytaj źródło, aby zobaczyć, gdzie tryb dołączania zmienia zachowanie, jeśli jest gdziekolwiek.

ilkkachu
źródło
-3

Jeśli potrzebujesz wydajności, użyj command >&-zamiast tego. To zamyka deskryptor pliku, zamiast go przekierowywać, więc nie trzeba tracić czasu na pisanie do niego różnych rzeczy.

db48x
źródło
3
Nie zamykaj strumieni mniejszych niż 3. Spowoduje to alias deskryptorów std * do losowych deskryptorów plików; potencjalnie z katastrofalnymi skutkami.
Joshua
7
Jeśli po prostu zamkniesz deskryptor pliku, program będzie wyświetlał błędy przy każdym wywołaniu zapisu, prawdopodobnie prowadząc do irytujących komunikatów o błędach i być może program zakończy się przed zakończeniem zadania.
ilkkachu