Search code examples
bashshellsh

How to ensure proper order of single command outputs in a Linux shell (dash, bash) script run by Textadept F5?


The described behavior occurs when I am running the code from Textadept text editor F5 (run code) feature (bash "%f") looking at the output in the output buffer. I can't reproduce it when running the script from the Terminal shell ... (thanks to Charles Duffy for pointing it out in the comments).

My current work around is to use sleep, but the amount of time is deliberately chosen and the approach may randomly fail no matter which value is used in sleep. Any idea how to assure the right order, so that the outcome of the output() function always for sure appears between -- 1 -- and -- 2 -- ?

output() { echo stdout;  echo stderr >&2; }
echo ' --1-- ' 
output  3>&2    1>&2    2>&3 
#sleep 0.001    # still causes the outcome of output be printed after echo '--2--'
sleep 0.01      # causes outcome of output be printed after echo '--1--'
echo ' --2-- '

Output to achieve:

 --1-- 
stdout
stderr
 --2-- 

Output without sleep or with too small sleep value:

 --1-- 
 --2-- 
stdout
stderr

Solution

  • Consider writing a wrapper script that combines stdout and stderr, and running your scripts behind that wrapper when you're using a tool like Textadept that reads those streams separately and then recombines them.

    For example, if you create a script, saved in a location on your PATH under the name on-stdout with the following contents:

    #!/bin/sh
    exec 2>&1  # make FD 2 (stderr) point to what's currently on FD 1 (stdout)
    exec "$@"  # replace ourselves with the script named by our arguments
    

    ...you could, instead of having Textadept run ./yourscript arg1 arg2, tell it to run on-stdout ./yourscript arg1 arg2. This would make the stderr handle received by yourscript be a copy of the stdout handle; because both descriptors point to the same handle, the operating system will then guarantee that write order is preserved.