2012-06-19 15 views
14

En el desarrollo de guiones de cerdo que utilizan el comando TIENDA tengo que borrar el directorio de salida para cada carrera o la secuencia de comandos se detiene y ofrece:Cómo forzar ALMACENAR (sobrescribir) a HDFS en Pig?

2012-06-19 19:22:49,680 [main] ERROR org.apache.pig.tools.grunt.Grunt - ERROR 6000: Output Location Validation Failed for: 'hdfs://[server]/user/[user]/foo/bar More info to follow: 
Output directory hdfs://[server]/user/[user]/foo/bar already exists 

Así que estoy la búsqueda de una solución interna a Pig elimine automáticamente el directorio, también uno que no se ahogue si el directorio no existe en la hora de la llamada.

En Pig Latin Reference encontré el comando de shell invocador fs. Desafortunadamente, la secuencia de comandos Pig se rompe cada vez que algo produce un error. Así que no puedo usar

fs -rmr foo/bar 

(i. E. Eliminar de forma recursiva), ya que se rompe si el directorio no existe. Por un momento pensé que podía usar

fs -test -e foo/bar 

que es una prueba y no debería romperse o eso creía. Sin embargo, Pig interpreta de nuevo el código de retorno test en un directorio no existente como un código de falla y se rompe.

Hay una JIRA ticket para el proyecto cerdo frente a mi problema y sugiere un parámetro opcional SOBRESCRIBIR o FORCE_WRITE para el comando TIENDA . De todos modos, estoy usando Pig 0.8.1 por necesidad y no hay tal parámetro.

Respuesta

40

Por fin encontré una solución en grokbase. Como encontrar la solución tomó demasiado tiempo, la reproduciré aquí y la agregaré.

Supongamos que desea almacenar la salida utilizando la sentencia

STORE Relation INTO 'foo/bar'; 

Luego, con el fin de eliminar el directorio, puede llamar al comienzo de la secuencia de comandos

rmf foo/bar 

No ";" o citas requeridas ya que es un comando de shell.

No puedo reproducirlo ahora pero en algún momento recibí un mensaje de error (algo sobre archivos perdidos) donde solo puedo suponer que rmf interfirió con map/reduce. Así que recomiendo poner la llamada antes de cualquier declaración de relación. Después de SET, los REGISTROS y los valores predeterminados deberían estar bien.

Ejemplo:

SET mapred.fairscheduler.pool 'inhouse'; 
REGISTER /usr/lib/pig/contrib/piggybank/java/piggybank.jar; 
%default name 'foobar' 
rmf foo/bar 
Rel = LOAD 'something.tsv'; 
STORE Rel INTO 'foo/bar'; 
+0

Aunque esto es de hecho muy bien, no es atómica.Prefiero hacerlo en tres pasos: 1) almacenar en 'foobar-tmp' 2) rmf foo/bar 3) mv 'foobar-tmp' en foo/bar –

+2

@MiguelPing: me parece que su enfoque debería toparse con mi problema inicial, pero para 'foobar-tmp' en lugar de' foo/bar'. Almacenar primero también puede producir ese error elusivo que tentativamente atribuí al mapa/reducir. Si su solución funciona de su lado, ¿podría convertirla en una respuesta con un script de ejemplo y proporcionar su número de versión de cerdo? – valid

+0

@valid mi solución es similar a la tuya, acabo de agregar un paso adicional para garantizar que si algo sucede entre 'rmf' y' STORE' (por ejemplo, excepción) no pierdas datos. Las secuencias de comandos Pig pueden fallar en cualquier momento, por lo que mi solución tampoco es atómica, pero al menos no corre el riesgo de perder datos. –

2

Una vez que se utiliza el comando FS, hay un montón de maneras de hacer esto. Para un archivo individual, acabé añadiendo esto al comienzo de mis guiones:

-- Delete file (won't work for output, which will be a directory 
-- but will work for a file that gets copied or moved during the 
-- the script.) 
fs -touchz top_100 
rm top_100 

Para un directorio

-- Delete dir 
fs -rm -r out 
Cuestiones relacionadas