4

I have a bash script (named opsin) which only manages the calling of Java binary. All arguments are forwarded with ${@:1} to Java binary.

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

This binary, opsin.jar, also accepts stdin so you can do

echo "abcd" | java -jar opsin.jar

But I can do the same with bash script above:

echo "abcd" | opsin

How is the stdin passed to

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

in bash script?

5

Magic!

In particular, the shell will fork(2) itself; this results in two (mostly) identical copies of the shell process; notably, the child shell process inherits a copy of standard input from the parent shell process:

   *  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)).

Then, the child shell process will call exec(3) to launch java, that is, the child shell process replaces itself with java. Through this call java obtains the copies of file descriptors inherited from the parent, and can act on the standard input thus passed along to it.

(There may be complications if a "close on exec" flag is set on a file descriptor, but that's not the default for the standard ones like standard input.)

Also, if the parent shell need not stick around in memory while java is running, the code can be written as:

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

So that java replaces the parent shell process instead of leaving a shell process needlessly lingering in memory.

For more details, Advanced Programming in the Unix Environment (APUE) has some chapters on the various fork, exec, dup, pipe system calls involved.

1
  • Thanks for answer. It seems there is still many I can learn about bash :) – jirinovo Feb 11 '17 at 10:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.