coproc
Run a command in the background
TLDR
Run a subshell asynchronously
Create a coprocess with a specific name
Write to a specific coprocess stdin
Read from a specific coprocess stdout
Create a coprocess which repeatedly reads stdin and runs some commands on the input
Create a coprocess which repeatedly reads stdin, runs a pipeline on the input, and writes the output to stdout
Create and use a coprocess running bc
SYNOPSIS
coproc [NAME] command [arguments...]
PARAMETERS
NAME
Optional. An array name where the file descriptors for the coprocess's pipes will be stored. If omitted, the default array name COPROC is used. NAME[0] holds the file descriptor for writing to the coprocess's standard input, and NAME[1] holds the file descriptor for reading from the coprocess's standard output.
command [arguments...]
The command and its arguments to be executed as the coprocess. This command runs in a separate subshell process.
DESCRIPTION
The coproc keyword in Bash (Bourne-Again SHell) provides a powerful mechanism for running commands asynchronously as "coprocesses," establishing a direct, bidirectional communication channel between the parent shell and the child process.
When invoked, coproc launches the specified command in a subshell, executing it in the background. Simultaneously, it creates two pipes: one for sending data to the coprocess's standard input, and another for receiving data from its standard output. The file descriptors (FDs) for these pipes are stored in a shell array. By default, this array is named COPROC, but a custom NAME can be provided. Specifically, NAME[0] (or COPROC[0]) holds the FD to which the parent shell writes data, which becomes the coprocess's standard input. Conversely, NAME[1] (or COPROC[1]) holds the FD from which the parent shell reads data, which originates from the coprocess's standard output.
This setup facilitates sophisticated inter-process communication (IPC) directly within a shell script. It allows the parent script to feed input to a long-running background process and consume its output dynamically, enabling shell-based client-server patterns or asynchronous task management. Unlike simple backgrounding with '&', coproc specifically establishes the I/O pipes, making interactive communication straightforward. It is particularly useful for scripting scenarios where real-time interaction with a background service or data processing pipeline is required.
CAVEATS
Bash Specific: coproc is a Bash shell built-in keyword, not a standard POSIX command. It will not work in other shells like sh, dash, or zsh (without Bash emulation).
File Descriptor Management: It's crucial to correctly manage the file descriptors. Unclosed descriptors can lead to resource leaks or unexpected behavior. Closing the write FD (e.g., COPROC[0]) is often necessary to signal EOF to the coprocess.
Error Handling: coproc itself doesn't provide robust error handling for the coprocess's failures. The shell must explicitly check the coprocess's exit status (e.g., using wait) and handle its stderr if needed (by redirecting it within the coproc command).
Debugging Challenges: Debugging I/O issues and race conditions with pipes can be challenging.
INTERACTING WITH THE COPROCESS
To send input to the coprocess's standard input: echo "data" >& ${COPROC[0]}
To read output from the coprocess's standard output: read -u ${COPROC[1]} variable
It is often necessary to close the write end of the pipe (e.g., exec ${COPROC[0]}<&-) after sending all input to signal EOF to the coprocess, allowing it to complete its processing.
JOB CONTROL AND PIDS
The coprocess runs as a background job. Its job ID and PID can be accessed via COPROC_PID (or NAME_PID if a custom NAME was used). Its job number can be seen with jobs. The parent shell can use wait to await its termination, kill to send signals, or disown to remove it from the job table.
FILE DESCRIPTOR BEHAVIOR
By default, coproc sets the coprocess's standard input to /dev/null. Standard output and standard error are inherited from the parent shell, but the coprocess's standard output is also connected to the read pipe (COPROC[1]). If standard error needs to be captured via the pipe, it must be explicitly redirected to standard output within the coproc command (e.g., coproc command 2>&1).
HISTORY
coproc was introduced in Bash 4.0 (released February 2009). Its addition aimed to provide a more convenient and robust way to manage asynchronous processes with direct bidirectional I/O channels from within Bash scripts, without needing to rely on external utilities like mkfifo or complex exec redirections and process substitutions. It streamlined inter-process communication for shell scripts.