- Table of contents
- Shell commands
Shell commands¶
bash
¶
Debugging: Printing out data¶
echo "BASH_SOURCE=[${BASH_SOURCE[@]}]" "BASH_ARGV=[${BASH_ARGV[@]}]" "\$0=[$0]" "\$@=[$@]" >&2
1st element of a list¶
echo "$(set -- *.ext; echo "$1")"
Waiting for a process¶
while test -e /proc/<PID>; do sleep 60; done; <commands>
A process putting itself in the background¶
if test -n "$in_background"; then # running in background unset in_background else # run in background export in_background=1 "$0" "$@" & echo "Running $0 in background as process $!" >&2 exit fi
svn
¶
Checking diffs¶
- Moved files:
st|grep ^A
- Remove the A prefixes,
svn di
the result, and check that there are no changes
- Deleted files:
st|grep ^D
- Changed files:
st|grep ^M
svn di
each changed file
Makefiles¶
Debugging: Printing out data¶
$(error $(var))
ed¶
substitution¶
echo $'1\n,s/a/b/\nwq'|ed --loose-exit-status --verbose file
fifos¶
- as long as a fifo has >= 1 reader, the writer will not receive SIGPIPE
- if a fifo/tty has > 1 reader, they will compete for who reads from the pipe buffer
- for this reason, when a new reader connects, it must then disconnect the existing reader to avoid competing for reads
- to do this, use SIGHUP in addition to SIGTERM because some processes (e.g.
bash -i
) ignore SIGTERM - the existing reader must be disconnected after connecting so that the fifo always has >= 1 reader
- to do this, use SIGHUP in addition to SIGTERM because some processes (e.g.
- for this reason, when a new reader connects, it must then disconnect the existing reader to avoid competing for reads
fifo pairs¶
terminal end shell end +---------------------------------------+ shell input: | >shell_in_fifo ----- <shell_in_fifo | +---------------------------------------+ +---------------------------------------+ shell output:| <shell_out_fifo ----- >shell_out_fifo | +---------------------------------------+
ttys¶
- the only reason to use a tty pair rather than a fifo pair is to make the shell (and processes it invokes) think it its input/output is from a terminal (i.e.
isatty()
returns true)- some commands (e.g. rsync) will change their output depending on whether their stdout is to a terminal, in order to avoid outputting escape sequences to a log file
terminal end shell end +--------------------+ +-----------------+ shell input: | >tty_terminal_end | | <tty_shell_end | | \ | | / | | =|===|= | | / | | \ | shell output:| <tty_terminal_end | | >tty_shell_end | +--------------------+ +-----------------+
- the terminal end is used by the terminal program (e.g.
sshd
, Terminal.app) to communicate with the shell.
it is not visible to the shell viatty
. - ttys are unusual in that the same tty file will go to different places when read from and written to
Unix¶
1 `man pty`
> FILES
.
persistent shells¶
- this is similar to the
screen
command, but uses the terminal's own scrollback- when a new reader connects, it will receive any buffered scrollback that the previous reader had not yet read
run a persistent shell¶
tail -f <shell_in|shell... 2>&1|SIGPIPE_ignoring_cat >shell_out # `tail -f` ignores EOF when a writer disconnects
SIGPIPE_ignoring_cat
runscat -u
but ignores SIGPIPE when a reader disconnects, and instead retriescat -u
until a new reader is connected-u
avoids blocking until an entire chunk of input is available- after the initial SIGPIPE,
cat -u
will block if there is no reader onshell_out
. for this reason, the first write toshell_out
needs to be done manually (using read/echo) and timed out. upon timeout, input needs to be flushed to/dev/null
for a period of time before retrying, to ensure that the shell's output buffer is always empty. (this allows the shell to run unblocked, even when there is no reader to receive its output.) upon success, writes can continue withcat -u
(under the assumption that the reader will read all input promptly and not block the shell). - upon SIGPIPE,
cat -u
will discard whatever data it most recently tried to write. this is not necessarily a problem, because data will be discarded anyway while no reader is connected (see above).
with reconnect scrollback¶
SIGPIPE_ignoring_cat
can also print the last n lines of output when a new reader connects (in case these lines were lost by the previous reader when it disconnected)- it would use an additional reread buffer for this, which is separate from any pipe buffer used by the
cat
functionality - the reread buffer would reset itself to its beginning every time SIGPIPE is received, so that the scrollback is always echoed first
- however, if a circular pipe buffer is used, a reread buffer could instead use an iterator over the circular buffer that's separate from its start pointer
- the reread buffer would advance the start pointer by the same # lines read by the read iterator
(unless the reread buffer had not yet filled up, in which case it would not change the start pointer)
- the reread buffer would advance the start pointer by the same # lines read by the read iterator
- it would use an additional reread buffer for this, which is separate from any pipe buffer used by the
patch into a persistent shell¶
cat >shell_in & cat <shell_out; kill %
- when using ttys, you must use the terminal end rather than the shell end output by
tty