2015-03-07 11 views
5

napisałem mały skrypt R czytać JSON, który działa w porządku, ale po rurociągów zRurociągi Rscript daje błąd po wyjściu

Rscript myscript.R | head 

The (pełny oczekuje) Wyjście wraca z błędem

Error: ignoring SIGPIPE signal 
Execution halted 

dziwne, że nie można jej usunąć za rurociągów STDERR do /dev/null z:

Rscript myscript.R | head 2>/dev/null 

to samo błędu g iven ... prawdopodobnie dlatego, że błąd pojawia się w poleceniu Rscript? Sugeruje mi to, że wyjście polecenia głównego to STDOUT.

  • Rurociągi STDOUT do /dev/null powraca jedynie komunikat o błędzie tylko
  • Rurociągi stderr do /dev/null zwraca komunikat o błędzie ...!

Potokowanie wyjścia do kota wydaje się być "niewidoczne" - nie powoduje to błędu.

Rscript myscript.R | cat | head 

Dalsze łańcuchowym rura jest możliwy po poleceniu cat ale czuje się jak może być coś ważnego ignorowanie przez nie zwracając się do błędu.

Czy istnieje ustawienie, którego należy użyć w skrypcie, aby zezwolić na rurociąg bez błędu? Chciałbym mieć gotowe skrypty R dla małych zadań, jak to ma miejsce w przypadku Pythona i Perla, a denerwujące byłoby zawsze dodawanie bezużytecznego cat.

Istnieje dyskusja na temat radzenia sobie z tym błędem w C here, ale nie jest dla mnie jasne, w jaki sposób będzie to dotyczyć skryptu R.

Edit W odpowiedzi na odpowiedź użytkownika @ lll, pełnego scenariusza użytkowej (powyżej zwanej jako 'myscript.R') jest

library(RJSONIO) 
note.list <- c('abcdefg.json','hijklmn.json') 
# unique IDs for markdown notes stored in JSON by Laverna, http://laverna.cc 
for (laverna.note in note.list) { 
    # note.file <- path.expand(file.path('~/Dropbox/Apps/Laverna/notes', 
    #         laverna.note)) 
    # For the purpose of this example run the script in the same 
    # directory as the JSON files 
    note.file <- path.expand(file.path(getwd(),laverna.note)) 
    file.conn <- file(note.file) 
    suppressWarnings(# warnings re: no terminating newline 
    cat(paste0(substr(readLines(file.conn), 2, 15)),'\n') # add said newline 
) 
    close(file.conn) 
} 

Rscript myscript.R wyjścia

"id":"abcdefg" 
"id":"hijklmn" 

Rscript myscript.R | head -1 wyjścia

"id":"abcdefg" 
Error: ignoring SIGPIPE signal 
Execution halted 

To nie dla mnie jasne, co będzie kończące „wczesne” tu

Edycja 2 To powtarzalne z readLines więc usunęliśmy informacji bibliotecznych specyficzne JSON w powyższym przykładzie. Skrypt i dummy JSON gisted here.

Edycja 3 Wydaje może być możliwe do podjęcia argumenty wiersza polecenia tym rur i przekazać je do pipe() - Postaram się to, kiedy mogę i rozwiązać problem.

Odpowiedz

2

Błąd jest po prostu spowodowany próbą zapisu na rurze bez procesu połączonego z drugim końcem.Innymi słowy, twój skrypt został już pobrany i pozostawiony do czasu, gdy rura zostanie osiągnięta i zostanie wywołana komenda HEAD.

Komenda sama w sobie może nie być numerem. może to być coś w skrypcie powodujące przedwczesne zakończenie lub wyścig przed osiągnięciem rury. Ponieważ uzyskujesz pełną wydajność, może to nie być aż tak niepokojące, jednak maskowanie błędu za pomocą innych poleceń CLI, jak wspomniano, prawdopodobnie nie jest najlepszym rozwiązaniem.


Rozwiązanie linii komend:

R ma kilka przydatnych poleceń do czynienia z przypadkami, w których warto interpreter czekać, a może tłumić wszelkie błędy, które normalnie byłyby wyjściowe do stderr.

Dla wiersza polecenia R, komunikaty o błędach napisane do „stderr” zostanie wysłany do terminal chyba ignore.stderr = TRUE. Mogą być zrobione (w najprawdopodobniej muszli) przez:

system("some command 2>&1", intern = TRUE) 

Istnieje również argument wait które mogłyby pomóc w utrzymaniu procesu żyje.

wait - logiczne (nie NA) wskazujące, czy interpreter R powinny czekać na polecenia do końca, lub uruchomić go asynchronicznie. Zostanie to zignorowane ( ) (a interpreter zawsze będzie czekał) , jeśli intern = TRUE.

system("Rscript myscript.R | head 2>&1", intern = TRUE) 

Powyższy będzie czekać, a wyjściowe błędy, jeśli są wyrzucane.

system("Rscript myscript.R | head", intern = FALSE, ignore.stderr = TRUE) 

Powyższe dane nie będą czekać, ale usuwają ewentualne błędy.

+0

Dzięki, zaktualizowałem moje pytanie. Nie widzę jednak żadnego przedwcześnie kończącego się procesu. Czy mógłbyś edytować swoją odpowiedź, aby wyjaśnić "zakończenie" (chyba że jest wystarczająco krótki na komentarz)? Skrypt jest pętlą for z ponad 2 elementami, które są przetwarzane na wyjściu, które widzę, więc nie rozumiem, jaki może być przedwczesny etap. –

+0

To może być 'close (file.conn)' być może tam, gdzie sprawy kończą się zbyt szybko. Czasami ten rodzaj zachowania jest również znany jako [stan wyścigu] (https://www.google.com/search?q=race+condition&ie=utf-8&oe=utf-8). Spróbuj krótko wypowiedzieć 'close (file.conn)', a następnie uruchom polecenie i zobacz, czy napotkasz ten sam problem. –

+0

Chodzi o to, że chcę skrypt, który może być połączony łańcuchem z nowymi poleceniami. Mogę wziąć potok jako argument w wywołaniu 'system()' jako 'system (paste0 (" Rscript myscript.R | ", args), intern = TRUE)' ... ale ... aby przekazać potok jak argumenty wydają się błędne? Działałoby to tylko dla jednego polecenia (użycie faktycznego '|' zakończyłoby czytanie argumentów), więc w jaki sposób wywołanie systemowe jest w stanie zaakceptować i wyprowadzić potokowy sygnał wyjściowy? –