53 lines
1.7 KiB
Markdown
53 lines
1.7 KiB
Markdown
|
# Shell pipes and fifo
|
||
|
Most bash "blocks" accept a redirection parameter at the end of their
|
||
|
declaration. This can replace where the output and errors are going
|
||
|
|
||
|
```bash
|
||
|
fn () {
|
||
|
echo "error" >&3
|
||
|
} 3>&2 2>file
|
||
|
# Prints "error" to the standard error. The real stderr is stored in ./file
|
||
|
```
|
||
|
|
||
|
- Functions, as above
|
||
|
- Sub-shells: `(echo "one"; echo "two") > file`
|
||
|
- Loops: `while (1); do echo "loop"; done > file`
|
||
|
|
||
|
Remember that redirection syntax looks like `[fd][< | >][&fd | file_path]`,
|
||
|
where `fd` is the index in the process' file descriptors. This works for `<` as
|
||
|
well. `|&` is identical to using `2>&1 |`
|
||
|
|
||
|
The order of IO redirection matters. Redirection will go to wherever the
|
||
|
redirected destination currently goes. Redeclaring a redirection doesn't work
|
||
|
|
||
|
```
|
||
|
┌3 writes to stdout
|
||
|
│ ┌stdout writes to stderr
|
||
|
│ │ ┌stderr writes to where 3 writes, so stdout
|
||
|
│ │ │
|
||
|
echo "one" 3>&1 1>&2 2>&3
|
||
|
```
|
||
|
|
||
|
To do this for the entire shell or script, use `exec`
|
||
|
|
||
|
```bash
|
||
|
exec 4>&1 # Holds onto reference to stdout
|
||
|
exec 1>/dev/null # Silences stdout and loses track of it
|
||
|
exec 1>&4 4>&1 # Restore stdout through reference in 4 and close 4
|
||
|
# Everything back to normal
|
||
|
```
|
||
|
|
||
|
`mkfifo` creates a named pipe, which can be easier to interact with between
|
||
|
scripts. Make sure it's being held open at use
|
||
|
|
||
|
```bash
|
||
|
mkfifo fifo
|
||
|
cat fifo >ofif & # Holds open fifo pipe and copies anything in there to ofif
|
||
|
exec 3>fifo # fd 3 reffers to pipe fifo
|
||
|
echo "double" >&3 # Writes to fifo. >fifo would close the pipe right after
|
||
|
exec 3>&- # Manually close the open pipe
|
||
|
```
|
||
|
|
||
|
The example above works similar to `tee` in logging everything in the pipe
|
||
|
|