Como o stdin é tratado neste script bash?

4

Eu tenho um script bash (chamado opsin ) que gerencia apenas a chamada do binário Java. Todos os argumentos são encaminhados com ${@:1} para o binário Java.

#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
java -jar $DIR/../bin-java/opsin/opsin.jar ${@:1}

Este binário, opsin.jar , também aceita stdin para que você possa fazer

echo "abcd" | java -jar opsin.jar

Mas posso fazer o mesmo com o script bash acima:

echo "abcd" | opsin

Como o stdin é passado para

java -jar $DIR/../bin-java/opsin/opsin.jar ${@:1}

no script bash?

    
por jirinovo 10.02.2017 / 17:47

1 resposta

5

Magia!

Em particular, o shell fork(2) ; isso resulta em duas cópias (na maior parte) idênticas do processo shell; Notavelmente, o processo de shell filho herda uma cópia da entrada padrão do processo de shell pai:

   *  The child inherits copies of the parent’s set of open file  descrip-
      tors.   Each  file  descriptor  in the child refers to the same open
      file description (see open(2)) as the corresponding file  descriptor
      in  the parent.  This means that the two descriptors share open file
      status flags, current file offset, and signal-driven I/O  attributes
      (see the description of F_SETOWN and F_SETSIG in fcntl(2)).

Em seguida, o processo do shell filho chamará exec(3) para iniciar o java , ou seja, o O processo de shell filho substitui o próprio por java . Por meio dessa chamada java obtém as cópias dos descritores de arquivos herdados do pai e pode agir na entrada padrão transmitida para ele.

(Pode haver complicações se um sinalizador "close on exec" estiver definido em um descritor de arquivo, mas esse não é o padrão para os padrões, como a entrada padrão.)

Além disso, se o shell pai não precisar ficar na memória enquanto java estiver em execução, o código pode ser gravado como:

#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
exec java -jar $DIR/../bin-java/opsin/opsin.jar ${@:1}

Para que java substitua o processo de shell pai em vez de deixar um processo de shell desnecessariamente atrasado na memória.

Para mais detalhes, a Programação Avançada no Ambiente Unix (APUE) tem alguns capítulos sobre as várias chamadas do sistema fork, exec, dup e pipe envolvidas.

    
por 10.02.2017 / 18:51