2015-03-07 14 views
5

ho scritto un piccolo script R per leggere JSON, che funziona bene, ma su di tubazioni conPiping rscript dà errore dopo l'uscita

Rscript myscript.R | head 

la (piena, atteso) uscita ritorna con un errore

Error: ignoring SIGPIPE signal 
Execution halted 

Stranamente non posso rimuovere questo convogliando STDERR a /dev/null utilizzando:

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

Lo stesso errore è g iven ... presumibilmente perché l'errore si verifica all'interno del comando Rscript? Il suggerimento per me è che l'output del comando head è tutto STDOUT.

  • Piping STDOUT a /dev/null restituisce solo il messaggio di errore solo
  • Piping STDERR a /dev/null restituisce il messaggio di errore ...!

Collegare l'output a cat sembra essere "invisibile" - questo non causa un errore.

Rscript myscript.R | cat | head 

ulteriore tubo di concatenamento è possibile dopo il comando cat, ma ci si sente come io possa ignorare qualcosa di importante da non affrontare l'errore.

Esiste un'impostazione che è necessario utilizzare all'interno dello script per consentire le tubazioni senza l'errore? Mi piacerebbe avere gli script R pronti per piccole attività come è fatto con Python e Perl, e sarebbe fastidioso dover sempre aggiungere un inutile cat.

Si sta discutendo sulla gestione di questo errore in C here, ma non mi è immediatamente chiaro come ciò si riferisca a uno script R.

Modifica In risposta a @ di lll risposta, lo script completo in uso (sopra chiamato come 'myscript.R') è

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 uscite

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

Rscript myscript.R | head -1 uscite

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

È non è chiaro per me quello che sarebbe terminato 'precoce' qui

Edit 2 E 'replicabile con readLines così ho rimosso JSON-specific delle biblioteche dettagli nell'esempio precedente. Script e manichino JSON con pugno here.

Edit 3 Sembra può essere possibile prendere gli argomenti della riga di comando tra cui tubi e passarli al pipe() - Cercherò questo quando posso e risolvere la questione.

risposta

2

L'errore è semplicemente causato da un tentativo di scrivere sulla pipe senza un processo collegato all'altro capo.In altre parole, lo script è già stato prelevato e lasciato quando viene raggiunto il pipe e viene chiamato il comando HEAD.

Il comando stesso potrebbe non essere il problema; potrebbe essere qualcosa all'interno dello script che causa una risoluzione anticipata o condizioni di competizione prima di raggiungere la pipa. Poiché si sta ottenendo un output completo, potrebbe non essere un problema, tuttavia mascherare l'errore con altri comandi CLI come indicato probabilmente non è l'approccio migliore.


La soluzione riga di comando:

R ha un paio di comandi utili per affrontare i casi in cui si potrebbe desiderare l'interprete di aspettare, o forse sopprimere eventuali errori che normalmente sarebbero uscita a stderr.

Per riga di comando R, i messaggi di errore scritti ‘stderr’ verrà inviato al terminale a meno che non ignore.stderr = TRUE. Essi possono essere catturati (nelle più probabili conchiglie) da:

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

C'è anche l'argomento wait che potrebbe contribuire a mantenere vivo il processo.

wait - logico (non NA) che indica se l'interprete di R dovrebbe attendere che il comando alla fine, o eseguirlo in modo asincrono. Questo sarà ignorato (e l'interprete aspetterà sempre) se intern = TRUE.

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

È possibile che questo avrebbe aspettato, e output errori, se presenti sono gettati.

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

Quanto sopra non attenderà, ma eliminerebbe eventuali errori.

+0

Grazie, ho aggiornato la mia domanda. Tuttavia, non riesco a vedere alcun processo di terminazione prematura. Potresti modificare la tua risposta per spiegare 'terminare' (a meno che non sia abbastanza breve per un commento)? Lo script è un ciclo for su 2 elementi, che vengono entrambi elaborati nell'output che vedo, quindi non capisco quale potrebbe essere lo stadio prematuro. –

+0

Potrebbe essere il 'close (file.conn)' forse dove le cose vengono terminate troppo rapidamente. A volte questo tipo di comportamento è noto anche come [condizione di competizione] (https://www.google.com/search?q=race+condition&ie=utf-8&oe=utf-8). Prova a commentare il file 'close (file.conn)' per un momento, quindi esegui il comando e verifica se riscontri lo stesso problema. –

+0

Il punto è che voglio uno script che può essere incatenato a nuovi comandi a volontà. Potrei prendere la pipe come argomento all'interno della chiamata 'system()' come system (paste0 ("Rscript myscript.R |", args), intern = TRUE) '... ma ... per passare una pipe in come argomenti sembra sbagliato? Funzionerebbe solo con un comando (usando un effettivo '|' terminerebbe la lettura degli argomenti), quindi come può una chiamata di sistema in grado di accettare e concatenare l'output in pipe? –