.\" $Id: Tee.man,v 2.13 2012/11/06 17:27:02 ksb Exp $ .\" by Kevin Braunsdorf .\" $Compile: Display%h .\" $Display: ${groff:-groff} -Tascii -man %f |${PAGER:-less} .\" $Display(*): ${groff:-groff} -T%s -man %f .\" $Install: %b -mDeinstall %o %f && cp %f $DESTDIR/usr/local/man/man1/Tee.1 .\" $Deinstall: ${rm-rm} -f $DESTDIR/usr/local/man/[cm]a[nt]1/Tee.1* .TH TEE 1L LOCAL .SH NAME Tee - advanced pipe fitting .SH SYNOPSIS .ds PN "Tee \fI\*(PN\fP [\fB\-a\fP\fBi\fP\fBv\fP] [\fB+\fP\fIspigots\fP] [\fB\-b\fP\~\fIblocksize\fP] [\fB\-R\fP\fIring\fP] [\fIfiles\fP] .br \fI\*(PN\fP \fB\-h\fP .br \fI\*(PN\fP \fB\-V\fP .SH DESCRIPTION .PP When a stream needs to be diverted to more than one destination a simple redirection won't do. \fI\*(PN\fP duplicates a stream standard output as well as to one or more \fIfiles\fP. .PP The simple case allows the data passing through a pipe to be recorded in a log file: .RS .nf \fI...\fP | \*(PN \-a /var/log/myapp | ... .fi .RE (This is not a replacement for the system logger, by the way.) .PP The \fIfiles\fP may be filenames or shell commands when prefixed by a pipe (|). The process style is intended for use with remote shell and dd to copy tapes and such. .PP A more advanced application might save the first and last lines of a sort output for later inspection: .RS .nf \fI...\fP | sort \fI...\fP| \*(PN '|head \-1 >first' '|tail \-1 >last' | \fI...\fP .fi .RE .PP A third style mocks the shell redirection duplication form allowing \fI\*(PN\fP to leverage already open files. For example to duplicate \fIstdout\fP to \fIstderr\fP in a pipeline one would: .RS .nf \fI...\fP | sort \fI...\fP| \fBTee '>&2'\fP | comm \fI...\fP .fi .RE .SH OPTIONS .TP \fB+\fP\fIspigots\fP Given enough destination \fIfiles\fP \fI\*(PN\fP must fork copies of itself to open all the requisite file descriptors. This integer specifies a lower limit than the system maximum to tune \fI\*(PN\fP's usage of file descriptors per process. .TP \fB\-a\fP Append to each \fIfile\fP in the list. The may be specifed for each file with by prefixing \fB>>\fP to the filename (which must be quoted from the shell). An explict prefix of \fB>\fP turns this option off for any \fIfile\fP specified, if it is set globally. .TP \fB\-b\fP \fIblocksize\fP Set the blocksize for the transfer. This only matters (for the most part) for transactions with device files or pipe fitting with dd(1). This does take all the common suffixes. .sp The default block size is small to speed output to terminal (or other interactive) devices. Larger transfer sizes save system calls but lead to surges in terminal output that make it impossible to read anything (as all the output comes out at the end of the process). Set a larger \fPblocksize\fP for bulk payloads (viz. 128k and 1m work well). .TP \fB\-h\fP Print a help message. .TP \fB\-i\fP Ignore interrupts. .TP \fB\-R\fP\fIring\fP This forces \fI\*(PN\fP to \fIfork\fP(2) multiple worker process that each buffer \fIblocksize\fP chunks of the input stream, then write their chunk to each output stream. Commonly \fB\-R2\fP is called "double buffering". Note that the specification must abut the option. .TP \fB\-v\fP Trace progress on \fIstderr\fP. A period (.) is output for each block fully transferred. A newline is output after each 72 blocks. In the case where more than one process is needed to honor all the destination \fIfiles\fP the last \fI\*(PN\fP in the pump will be the original process and the one to output all the trace information. .TP \fB\-V\fP Show version information. .SH EXAMPLES .TP .nf dd if=/dev/rmt/0h bs=20b | \*(PN \-b 20b /dev/rmt/1h >/dev/rmt/2h .fi Copy the tar tape on the zero tape drive to both tape 1 and tape 2 in high density mode. Note that one destination tape is opened by \fI\*(PN\fP, the other is \fIstdout\fP. .TP .nf finger | \*(PN '|wc \-l' .fi Output the finger table followed by the number of lines in that output. .TP \fI\*(PN\fP '|awk "BEGIN {sum=0;} {sum += \e$1;} END {print sum;}"' F8 .fi Build 8 4Meg files of zeros. This might make a good disk timing test. .TP .nf dd if=/dev/zero count=512 bs=8k | \fI\*(PN\fP \-R4 \-b 8k F1 F2 F3 F4 F5 F6 F7 >F8 .fi Same a above, but use quad-buffer logic to keep 4 CPUs busy to build the files. .TP .nf mkiso\fI...\fP | \fI\*(PN\fP '|ssh h1 cat \>fs.iso' '|ssh h2 cat \>fs.iso' >fs.iso .fi Create a large ISO filesystem send it to 2 other hosts (h1, h2) and keep a local copy in \*(lqfs.iso\*(rq. .TP .nf \fI\*(PN\fP \-b 19827608\e? \-V .fi Ouptut the table of common byte multipliers with the version information. .\" and my phone number is in there .TP .nf \fI\*(PN\fP \-R \-V .fi Output version information as well as the default for the \fIring\fP specification. .TP .nf \fIsource\fP | \fI\*(PN\fP \-R2 | \fIdestination\fP .fi Double buffer the output of \fIsource\fP to \fIdestination\fP. This sometimes helps with overall throughput when both the input and output processes have uneven transaction times (viz. tape devices or processes that block at odd times). .TP .nf \fIsource\fP | \fI\*(PN\fP '>>../common/log' last.run | \fI...\fP .fi Use the explicit append notation to append to a common log file and record what we appended in a local file. .TP .nf \fIsource\fP | \fI\*(PN\fP \-a ../common/log '>last.run' | \fI...\fP .fi Same a the above, but invert the exception logic. .SH BUGS It is marginally more clever to reach out with \fBssh \-n\fP to read a remote tape than it is to push from the source machine due to the network overhead. .PP \fI\*(PN\fP could handle the splitting of long \fIfiles\fP lists better: in the case where we have to build 5 processes we might split the load between the processes more evenly (rather then 4 fulls and the last one with 1 or 2 destinations). .PP It might be argued that \fB\-R\fP should be spelled \fB\-P\fP to make it look more like other "ksb tools". But it is too late now. .PP A threaded version of this would be more clever, but single charater I/O to (from) a pipe is almost free. Still, user level mutext would be better. .SH AUTHOR Kevin S Braunsdorf .br NonPlayer Character Guild .br k-s-b at no-spam-me removed npcguild.org .SH HTML See the explode module \fBpipering.html\fP in /usr/local/lib/explode. .SH "SEE ALSO" .hlm 0 sh(1), dd(1), wc(1), ssh(1), logger(1), awk(1), finger(1)