1

While trying to solve other problems, I have come across the following bash script in Alex B's answer in this question:

#!/bin/bash

(
  # Wait for lock on /var/lock/.myscript.exclusivelock (fd 200) for 10 seconds
  flock -x -w 10 200 || exit 1

  # Do stuff

) 200>/var/lock/.myscript.exclusivelock

I have problems understanding that script. According to flock's manual, the file descriptor (the 200) in flock -x -w 10 200 must relate to an open file.

Where is that descriptor / file opened? If it is the 200>/var/lock/.myscript.exclusivelock which opens the descriptor, that would mean that this part is executed before the subshell, which is the opposite of what I have thought when I initially have looked at this script.

This leads me to my question: What is the execution order of subshells in bash, in relation to the main script (i.e. the script opening the subshells) as well as in relation to other subshells which the same main script might spawn?

From reading other articles and the bash manual, I believe I have only learned that subshells are executed "concurrently", but I didn't see any statement explaining if there are execptions from this (one obvious exception would be when the main script would need the output of a subshell, like echo foo $(cat bar)).

Binarus
  • 4,005
  • 3
  • 25
  • 41

1 Answers1

2

200>, the redirection operator, opens the file using descriptor 200. It is indeed processed before the subshell. That file descriptor is then inherited by the subshell.

There is nothing inherently concurrent about subshells. You may be thinking of pipelines, like a | b | c, where a, b, and c are all commands that run concurrently. The fact that each is run in a subshell (usually a subprocess proper, if they are external commands, but even shell built-ins execute in a subshell) is an implementation detail of the pipeline.


To elaborate,

  1. First, the shell parses this command. It identifies the complex command (...) with an output redirection.

  2. It opens /var/lock/.myscript.exclusivelock in write mode on file descriptor 200.

  3. It executes the subshell, which inherits all open file descriptors, including 200.

  4. In the subshell, it executes flock, which inherits all open file descriptors from its parent, the subshell. It does its thing on file descriptor 200, as requested by its argument.

  5. Once the subshell exits, any file opened by one of its redirection operators is closed by the shell.

chepner
  • 497,756
  • 71
  • 530
  • 681
  • Could you please elaborate a bit? What mechanism makes `bash` execute the `200> ...` part before the subshell? After all, `bash` can't know that this file descriptor is needed later, because `bash` does not know about the `flock` syntax, so it can't magically detect that it needs to execute the subshell after the main part. – Binarus Aug 31 '18 at 11:20
  • 1
    Sure it can. The evaluation process is to parse the command line, during which process all the redirections are identified. The required files are opened in order to pass the correct file descriptors to the command. A subshell is just one example of a *compound* command (other examples include `if` statement, `while` statements, and command groups `{...}`), as opposed to a simple command (which is just a command name and its arguments). – chepner Aug 31 '18 at 11:24
  • 1
    `flock` is simply acting on file descriptor 200 which it receives from its parent, which in this case is the subshell command. – chepner Aug 31 '18 at 11:24
  • OK, thanks, accepted and +1. Your explanation has made clear that the subshell invocation plus the redirection is just **one** command (and not multiple commands). For me, this was the key to understanding; for some reason, I initially didn't realize this in all clarity. – Binarus Aug 31 '18 at 13:30