1

Yesterday I got some clarification around using flock and some simple concepts are becoming clear to me.

My question now is around sub-shells. Take a look at this block

(
 flock -s 200 
 # ... commands executed under lock ... 
) 200>/var/lock/mylockfile

My understanding is 200>/var/lock/mylockfile runs before flock -s 200, yet if I try something like this

( echo This is a sub-shell ) command

I get an error from BASH

-bash: syntax error near unexpected token `command'

Introducing a semi-colon

( echo This is a sub-shell ); command

fixes the error, but causes command to run after the sub-shell returns.

So I'm wondering how the initial example causes the redirect to run first. Is it something to do with precedence of the > over sub-shell (list) notation? Looking in the BASH manpage I find

Operators are evaluated in order of precedence. Sub-expressions in parentheses are evaluated first and may override the precedence rules above.

Community
  • 1
  • 1
quickshiftin
  • 66,362
  • 10
  • 68
  • 89
  • FYI, subshells and lists are syntactically different things -- they have different parser rules, despite using the same character (and thus looking the same to the lexer). – Charles Duffy Feb 11 '14 at 18:07

2 Answers2

2

200>/var/lock/mylockfile is, in this context, information about how the subshell should be configured (how its redirection is supposed to be set up). It's not a separate command.

This is true in the same way that

echo "foo" >bar.txt

...always does the redirection first, as does

>bar.txt echo "foo"

In neither of these cases does order matter at all.

A subshell is similar in this respect -- it's just a compound command, and like any other command, it can have redirections specified either at its beginning or its end.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • Thanks for this Charles, I presumed I had a fundamental misunderstanding. I'll keep studying. – quickshiftin Feb 11 '14 at 18:10
  • 3
    By the way, new versions of bash (4.1+) will allocate FDs for you, so you don't have to hardcode numbers. Thus, you can use `{lock_fd}>/path/to/lockfile` and `flock -s "$lock_fd"` – Charles Duffy Feb 11 '14 at 18:11
1

200>/var/lock/mylock; only creates mylock but that's all. For instance,

$ 200>/var/lock/mylock;
$ echo "hello" >&200
bash: 200: bad file descriptor.

doesn't work. If you want this to run, add exec :

$ exec 200>/var/lock/mylock;
$ echo "hello" >&200
$ cat /var/lock/mylock
hello

Now about subshells : when writing

(
   ...
) 200>/var/lock/myfile

bash creates a child using fork(), then the child redirects 1 to 200 using dup2, then parses and executes the code inside ( ... ).

Thus if you want to create the file before the subshell, a solution is

exec 200> /var/lock/file
(
  ...
) >&200
Edouard Thiel
  • 5,878
  • 25
  • 33
  • Thank you Edouard, this is also *very* helpful. In looking at the code I've borrowed from yesterday, I was wondering about the use of `exec` for the redirection. I'll study your examples here closely. – quickshiftin Feb 11 '14 at 18:22
  • Nice. I suppose I need to just read through the Advanced Bash-Scripting Guide. The manpage alone leaves something to be desired. – quickshiftin Feb 11 '14 at 18:27
  • @quickshiftin, I'd strongly suggest the BashGuide instead: http://mywiki.wooledge.org/BashGuide; we often have to help people unlearn bad habits the ABS taught them in freenode's #bash. – Charles Duffy Feb 11 '14 at 19:32
  • Thanks Charles, I'll give this a look as well. – quickshiftin Feb 11 '14 at 19:51