¿Por qué el proceso hijo devuelve el estado de salida = 32512 en Unix?

5 minutos de lectura

Avatar de usuario de Mihran Hovsepyan
Mihran Hovsepyan

En mi programa, estoy ejecutando el comando dado y obteniendo resultados (registro y estado de salida). Además, mi programa debe admitir comandos específicos de shell (es decir, comandos que contienen caracteres específicos de shell ~(tild),|(pipe),*). Pero cuando trato de correr sh -c ls | wc en mi directorio de inicio a través de mi programa falló y su estado de salida fue 32512, también en stderr stream "sh: ls | wc: command not found" fue impreso.

Pero lo interesante es que el comando sh -c ls | wc funciona correctamente si lo ejecuto en Shell.

¿Cuál es el problema? O más preferible, ¿cómo puedo ejecutar comandos específicos de shell a través de mi programa (es decir, qué comando con qué parámetros debo ejecutar)?

La siguiente parte del código está en la parte secundaria después de fork(). Ejecuta el comando.

tokenized_command es std::vector<std::string> donde en mi caso "sh", "-c", "ls", "|", "wc" están almacenados, también he intentado almacenar allí "sh", "-c", "\"ls | wc\"" pero el resultado es el mismo. command es char * donde se almacena la línea de comando completa.

        boost::shared_array<const char *> bargv(new const char *[tokenized_command.size() + 1]);
        const char **argv = bargv.get();
        for(int i = 0; i < tokenized_command.size(); ++i)
        {
            argv[i] = tokenized_command[i].c_str();
            printf("argv[%d]: %s\n", i, argv[i]); //trace
        }
        argv[tokenized_command.size()] = NULL;

        if(execvp(argv[0], (char * const *)argv) == -1)
        {
            fprintf(stderr, "Failed to execute command %s: %s", command, strerror(errno));
            _exit(EXIT_FAILURE);
        }

PD

yo se que usando system(command) en cambio execvp puede resolver mi problema. Pero system() espera hasta que finalice el comando, y esto no es lo suficientemente bueno para mi programa. Y también estoy seguro de que en la implementación de system() se usa una de las funciones de la familia exec, por lo que el problema se puede resolver a través de exec también, pero no sé cómo.

  • Proporcione un código que muestre cómo está ejecutando el comando de shell y recopilando el resultado y el estado de salida.

    –Oliver Charlesworth

    12 de abril de 2011 a las 16:14

  • no vi nada relacionado con el c o c++ etiquetas, así que las eliminé.

    – Sam Molinero

    12 de abril de 2011 a las 17:01

  • He añadido algo relacionado con el c y c++.

    – Mihran Hovsepyan

    12 de abril de 2011 a las 17:03

avatar de usuario de ikegami
ikegami

execvp toma una ruta a un ejecutable y argumentos con los que ejecutar ese ejecutable. No toma comandos de Bourne Shell.

ls | wc es un comando de Bourne Shell (entre otros), y no se puede desglosar en la ruta a un ejecutable y algunos argumentos debido al uso de una canalización. Esto significa que no se puede ejecutar usando execvp.

Para ejecutar un comando de Bourne Shell usando execvphay que ejecutar sh y pasar -c y el comando para argumentos.

Así que quieres ejecutar ls | wc usando execvp.

char *const argv[] = {
    "sh",
    "-c", "ls | wc",  // Command to execute.
    NULL
};

execvp(argv[0], argv)

aparentemente lo intentaste

char *const argv[] = {
    "sh",
    "-c", "ls",  // Command to execute.
    "|",         // Stored in called sh's $0.
    "wc",        // Stored in called sh's $1.
    NULL
};

Eso sería lo mismo que el comando Bourne Shell sh -c ls '|' wc.

Y ambos son muy diferentes al comando de shell. sh -c ls | wc. Eso sería

char *const argv[] = {
    "sh",
    "-c", "sh -c ls | wc",  // Command to execute.
    NULL
};

pareces pensar | y wc se pasan a la shpero ese no es el caso en absoluto. | es un carácter especial que da como resultado una canalización, no un argumento.


En cuanto al código de salida,

Bits 15-8 = Exit code.
Bit     7 = 1 if a core dump was produced.
Bits  6-0 = Signal number that killed the process.

32512 = 0x7F00

Por lo tanto, no murió debido a una señal, no se produjo un volcado de memoria y salió con el código 127 (0x7F).

No está claro qué significa 127, por lo que debería ir acompañado de un mensaje de error. Intentaste ejecutar el programa ls | wcpero no existe tal programa.

  • No, recibo un mensaje de error. Siento no haberlo puesto aquí. sh: ls | wc: command not found este es el mensaje/

    – Mihran Hovsepyan

    12 de abril de 2011 a las 16:53

  • @Mihran Hovsepyan, está intentando ejecutar el archivo llamado “ls | wc“en lugar del comando Bourne Shell”ls | wc“. Si desea ejecutar un comando de Bourne Shell, debe iniciar un Bourne Shell y pasarle el comando. sh -c 'ls | wc'.

    – ikegami

    12 de abril de 2011 a las 17:47

  • No quiero la cáscara del almuerzo. No quiero ejecutar comandos específicos de shell desde mi programa.

    – Mihran Hovsepyan

    13 de abril de 2011 a las 5:23

  • @Mihran Hovsepyan. No está claro lo que quieres decir con eso. Si quiere evitar ejecutar un shell, entonces simplemente no puede ejecutar ls | wc. Si quiere decir que quiere hacer que el shell sea configurable, realmente no veo el punto, pero nada lo detiene.

    – ikegami

    13 de abril de 2011 a las 7:47

  • @Mihran Hovsepyan. Si desea evitar ejecutar un shell, deberá iniciar dos procesos (ls en uno, wc en otro), creando una tubería entre ellos en el proceso. También tendrás que gestionar la finalización de dos procesos en lugar de uno. Incluso podría ser más fácil implementar la funcionalidad que desea de ls y wc tú mismo.

    – ikegami

    13 de abril de 2011 a las 7:50

deberías ejecutar sh -c 'ls | wc'.

Opción -c espera un comando en forma de cadena. En shell, por supuesto, está funcionando, porque no hay diferencia entre el desove ls y redirigir la salida a wc y lanzamiento ls | wc en capa separada.

  • En realidad, probablemente estaba generando un shell separado para ejecutar ls y también generando un wc para recibir su salida.

    – Jonathan

    12 de abril de 2011 a las 16:39

  • Sí, lo sé, simplemente no lo subrayé.

    – pajtón

    12 de abril de 2011 a las 16:42

¿Ha sido útil esta solución?