GNU/Linux >> Tutoriales Linux >  >> Linux

¿La forma portátil (posix) de lograr la sustitución de procesos?

Algunas conchas, como bash , admite Sustitución de procesos, que es una forma de presentar la salida del proceso como un archivo, como este:

$ diff <(sort file1) <(sort file2)

Sin embargo, esta construcción no es POSIX y, por lo tanto, no es portátil. ¿Cómo se puede lograr la sustitución de procesos de una manera compatible con POSIX? (es decir, uno que funciona en /bin/sh ) ?

nota:la pregunta no es cómo diferenciar dos archivos ordenados, ¡ese es solo un ejemplo artificial para demostrar la sustitución del proceso!

Respuesta aceptada:

Esa característica fue introducida por ksh (documentado por primera vez en ksh86) y estaba haciendo uso de /dev/fd/n función
(agregada de forma independiente en algunos sistemas BSD y AT&T anteriormente).
En ksh y hasta ksh93u, no funcionaría a menos que su sistema fuera compatible con /dev/fd/n . zsh, bash y ksh93u+ y superiores pueden hacer uso de canalizaciones temporales con nombre (canalizaciones con nombre agregadas en System III) donde /dev/fd/n no están disponibles.

En sistemas donde /dev/fd/n está disponible (POSIX no los especifica),
puede realizar la sustitución del proceso (p. ej., diff <(cmd1) <(cmd2) ) usted mismo con:

{
  cmd1 4<&- | {
    # in here fd 3 points to the reading end of the pipe
    # from cmd1, while fd 0 has been restored from the original
    # stdin (saved on fd 4, now closed as no longer needed)

    cmd2 3<&- | diff /dev/fd/3 -

  } 3<&0 <&4 4<&- # restore the original stdin for cmd2

} 4<&0 # save a copy of stdin for cmd2

Sin embargo, eso no funciona con ksh93 en Linux como allí, las tuberías de shell se implementan con pares de sockets en lugar de tuberías y abriendo /dev/fd/3 donde fd 3 apunta a un socket no funciona en Linux.

Aunque POSIX no especifica /dev/fd/n , especifica canalizaciones con nombre. Las canalizaciones con nombre funcionan como canalizaciones normales, excepto que puede acceder a ellas desde el sistema de archivos. El problema aquí es que debe crear temporales y limpiarlos después, lo cual es difícil de hacer de manera confiable, especialmente considerando que POSIX no tiene un mecanismo estándar (como un mktemp -d como se encuentra en algunos sistemas) para crear archivos o directorios temporales, y el manejo de señales (para limpiar al colgar o eliminar) también es difícil de hacer de forma portátil.

Podrías hacer algo como:

tmpfifo() (
  n=0
  until
    fifo=$1.$$.$n
    mkfifo -m 600 -- "$fifo" 2> /dev/null
  do
    n=$((n + 1))
    # give up after 20 attempts as it could be a permanent condition
    # that prevents us from creating fifos. You'd need to raise that
    # limit if you intend to create (and use at the same time)
    # more than 20 fifos in your script
    [ "$n" -lt 20 ] || exit 1
  done
  printf '%s\n' "$fifo"
)

cleanup() { rm -f -- "$fifo"; }

fifo=$(tmpfifo /tmp/fifo) || exit

cmd2 > "$fifo" & cmd1 | diff - "$fifo"

cleanup

(sin ocuparse del manejo de la señal aquí).

Relacionado:¿El proceso se completó inmediatamente después de abrir la Terminal y es imposible agregar comandos?
Linux
  1. ¿Nuevo proceso principal cuando muere el proceso principal?

  2. ¿Cuál es la mejor manera de enviar una señal a todos los miembros de un grupo de procesos?

  3. ¿Cuál es la definición de una sesión en Linux?

  4. ¿Hay alguna manera de escuchar el proceso?

  5. ¿Cuál es la forma más segura y portátil de invocar el binario de eco?

Personalización de Grub de forma sencilla:Grub-customizer

SIGTERM vs SIGKILL:¿Cuál es la diferencia?

Sustitución de procesos:una forma poco común pero avanzada de redirección de entrada/salida en Linux

Instale Postman Ubuntu 18.04:¡La forma más fácil!

¿Cuál es el significado de POSIX?

Cómo recuperar mediante programación el GID de un proceso en ejecución