.\" Copyright (c) 2022 Joost van Baal-Ilić .TH "caspar" 7 "7 сеп 2022" "caspar 20220907" "MISCELLANEOUS " .po 2m .de ZI .\" Zoem Indent/Itemize macro I. .br 'in +\\$1 .nr xa 0 .nr xa -\\$1 .nr xb \\$1 .nr xb -\\w'\\$2' \h'|\\n(xau'\\$2\h'\\n(xbu'\\ .. .de ZJ .br .\" Zoem Indent/Itemize macro II. 'in +\\$1 'in +\\$2 .nr xa 0 .nr xa -\\$2 .nr xa -\\w'\\$3' .nr xb \\$2 \h'|\\n(xau'\\$3\h'\\n(xbu'\\ .. .if n .ll -2m .am SH .ie n .in 4m .el .in 8m .. .SH NAME caspar - Makefile snippets for common tasks .SH SYNOPSIS In a Makefile, write either .di ZV .in 0 .nf \fC include caspar/mk/caspar\&.mk .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR or .di ZV .in 0 .nf \fC include caspar/mk/docbook\&.mk .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR or .di ZV .in 0 .nf \fC include caspar/mk/pod\&.mk .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR \&. .SH DESCRIPTION Caspar offers Makefile snippets for common tasks, like installing (configuration) files, or typesetting LaTeX, DocBook XML and DocBook SGML documents\&. The typesetting functionality is delivered by \fIdocbook\&.mk\fP and \fIpod\&.mk\fP\&. This is documented in \fBcaspar-typesetting(7)\fP\&. The installing-stuff functionality is delivered by \fIcaspar\&.mk\fP\&. (That\&'s what the rest of the manual will talk about\&.) It enables one to run \&'make install\&' from within a tree which typically holds configuration files, managed using Subversion (or git or any other version control system, for that matter)\&. It is useful in cases like this: all configuration files of some host are under version control, and, after commiting a change to CVS, you want to be able to easily install the new configuration file on the host\&. With \fBcaspar\fP, all you have to do is specify the hostname in one place, and specify the name of the target directory in each CVS directory\&. It is comparable with other tools for Unix system administrators like puppet and cfengine\&. Main difference: the caspar code consists of less than 100 lines of GNU Make\&. .SH USAGE Within a CVS tree, create a file \fIinclude/install\&.mk\fP, with contents like e\&.g\&. .di ZV .in 0 .nf \fC csp_UHOST = root@some\&.host\&.somewhere include caspar/mk/caspar\&.mk .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR \&. Within each other directory of the CVS tree which holds files, create a Makefile, which looks like e\&.g\&. .di ZV .in 0 .nf \fC csp_DIR = /some/dir/ectory/ include \&.\&./\&.\&./include/install\&.mk .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR \&. If you\&'d like to use the \fIinstall-recursive\fP target too, in directories which hold subdirectories (but not files), you\&'ll have to create a Makefile which looks something like .di ZV .in 0 .nf \fC include \&.\&./\&.\&./include/install\&.mk .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR \&. From within the CVS tree, one can call: .di ZV .in 0 .nf \fC make -diff make -install make diff make install make load make make install-recursive .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR Calling \fCmake -diff\fP shows the diff between the local file and the file as currently installed on the remote location\&. Calling \fCmake install\fP (or \fCmake\fP) now will scp all files in the current directory to the remote location\&. The \fIinstall-recursive\fP target descends down the tree, and calls \fCmake install\fP in each subdirectory\&. Of course, you\&'ll have to be able to ssh directly as root to the remote host to get this working (if you\&'d like to use \fCcsp_UHOST = root@some\&.host\&.somewhere\fP)\&. If you don\&'t like this, and would like to have a \fCPermitRootLogin no\fP in your \fC/etc/ssh/sshd_config\fP, you can use csp_sucp(1)\&. See below\&. .SH VARIABLES The variables one can set in a calling Makefile are: .ZI 2m "\fCcsp_UHOST\fP" \& .br user@host, reachable using \fC$(csp_PUSH)\fP (which is scp by default) .in -2m .ZI 2m "\fCcsp_UHOSTS\fP" \& .br space separated list of user@host items, reachable using \fC$(csp_PUSH)\fP .in -2m .ZI 2m "\fCcsp_DIR\fP" \& .br directory on host, reachable using function \fC$(csp_PUSH)\fP .in -2m .ZI 2m "\fCcsp_PUSH\fP" \& .br make function for pushing files to remote location\&. Usually, this is a wrapper around a script or program\&. The function will be passed 4 arguments: \fI[user@]host\fP, remote \fIdirectory\fP and local \fIfilename\fP\&. \fI[user@]host\fP will be set to all elements of \fC$(csp_UHOSTS)\fP; \fIdirectory\fP will be set to \fC$(csp_DIR)\fP\&. Currently, \fC$(csp_scp_FUNC)\fP, \fC$(csp_cp_FUNC)\fP and \fC$(csp_sucp_FUNC)\fP are supported as push plugins\&. If \fCcsp_PUSH\fP is unset, the default \fC$(csp_scp_FUNC)\fP is used\&. .in -2m .ZI 2m "\fCcsp_LOAD\fP" \& .br the \&`load\&' target depends upon these targets\&. .in -2m .ZI 2m "\fCcsp_BUILD\fP" \& .br the \&`build\&' target depends upon these targets\&. .in -2m .ZI 2m "\fCcsp_CP\fP" \& .br cp binary, just "cp" by default .in -2m .ZI 2m "\fCcsp_SCP\fP" \& .br scp binary, just "scp" by default .in -2m .ZI 2m "\fCcsp_SUCP\fP" \& .br script wrapping sudo in ssh, "csp_sucp" by default .in -2m .ZI 2m "\fCcsp_EXTRAFILES\fP" \& .br extra files which should be installed\&. Can be used to include files starting with a dot\&. .in -2m .ZI 2m "\fCcsp_TABOOFILES\fP" \& .br files which should never be installed\&. Set to \fCMakefile \&.%\&.swp %~ #%# pod2htmd\&.tmp pod2htmi\&.tmp\fP by default\&. .in -2m .ZI 2m "\fCcsp_TABOOFILES_ADD\fP" \& .br extra files which should never be installed; added to list in \fCcsp_TABOOFILES\fP\&. .in -2m .ZI 2m "\fCcsp_TABOOFILES_SKIP\fP" \& .br files which should be installed, even if in initial \fCcsp_TABOOFILES\fP list\&. Removed from \fCcsp_TABOOFILES\fP list\&. .in -2m .ZI 2m "\fCcsp_TABOODIRS\fP" \& .br directories to exclude in install-recursive target\&. set to \fCCVS \&.svn\fP by default\&. .in -2m .ZI 2m "\fCcsp_TABOODIRS_ADD\fP, \fCcsp_TABOODIRS_SKIP\fP" \& .br see \fCcsp_TABOOFILES\fP equivalents\&. .in -2m .ZI 2m "\fCcsp_UHOSTS_SUBSET\fP" \& .br override csp_UHOSTS: don\&'t push to csp_UHOSTS, but to the intersection of this space separated list of user@host items and csp_UHOSTS\&. .in -2m The following variables might get phased out or removed soonish: .ZI 2m "\fCcsp_CPFLAGS\fP" \& .br extra arguments to pass to cp invocation, none by default .in -2m .ZI 2m "\fCcsp_SCPFLAGS\fP" \& .br extra arguments to pass to scp invocation, e\&.g\&. \&'\fC-i \&.ssh/id_rsa-root\fP\&' .in -2m .SH EXAMPLES Some examples: \fBUsing csp_UHOST\fP .br This is the simplest way to use caspar\&. \fIMakefile\fP is .di ZV .in 0 .nf \fC csp_UHOST = root@some\&.host\&.somewhere csp_DIR = /etc/ include caspar/mk/caspar\&.mk .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR Now, running "make" will scp all files in the current directory to \fCroot@some\&.host\&.somewhere:/etc/\fP\&. \fBMore hosts, not scp but sudo via ssh: using csp_PUSH\fP .br \fIMakefile\fP is .di ZV .in 0 .nf \fC csp_UHOSTS = root@some\&.host\&.somewhere root@some\&.other\&.host csp_PUSH = $(csp_sucp_FUNC) csp_DIR = /etc/ include caspar/mk/caspar\&.mk .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR Now, running "make" will use csp_sucp(1) to install all files in the current directory to both root@some\&.host\&.somewhere:/etc/ and root@some\&.other\&.host:/etc/\&. If a file named \fCfstab\fP is present in the current directory, running "make fstab-install" will just install that one file\&. If you need to sudo(1) to another user on the remote host, add something like .di ZV .in 0 .nf \fC csp_XARG = postgres .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR \&. (If such a username is not supplied, sudo (and csp_sucp) use the default: root\&.) \fBOverriding csp_UHOSTS: csp_UHOSTS_SKIP\fP .br If one or some of your hosts are temporarily unavailable, and you\&'d like to push your files to the hosts which are alive, you can temporarily override your csp_UHOSTS\&. E\&.g\&., when some\&.other\&.host is not available: .di ZV .in 0 .nf \fC % cat Makefile csp_UHOSTS = root@some\&.host\&.somewhere root@some\&.other\&.host csp_DIR = /etc/ include caspar/mk/caspar\&.mk % make install csp_UHOSTS_SKIP=root@some\&.other\&.host scp hosts root@some\&.host\&.somewhere:/etc/ scp fstab root@some\&.host\&.somewhere:/etc/ .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR \fBOverriding csp_UHOSTS in a smart way: csp_UHOSTS_SUBSET\&. Using multiple groups of hosts\&. Recursive make made easy\&.\fP .br If you have lots of subdirectories holding information for lots of groups of hosts, while this run you just want to install for a small group (or 1) hosts, csp_UHOSTS_SUBSET is useful\&. Suppose your casparized tree looks like .di ZV .in 0 .nf \fC Makefile apache/include/install\&.mk apache/etc/apache2/Makefile apache/etc/apache2/envvars php/include/install\&.mk php/etc/php4/apache/Makefile php/etc/php4/apache/php\&.ini grub/include/install\&.mk grub/boot/grub/Makefile grub/boot/grub/menu\&.lst logrotate/include/install\&.mk logrotate/etc/Makefile logrotate/etc/logrotate\&.conf nrpe/include/install\&.mk nrpe/debian/etc/default/Makefile nrpe/debian/etc/default/nagios-nrpe-server .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR The file \fIapache/etc/apache2/Makefile\fP is: .di ZV .in 0 .nf \fC csp_DIR = /etc/apache2/ include \&.\&./\&.\&./include/install\&.mk .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR (all other \fIMakefile\fPs are similar)\&. The file \fIapache/include/install\&.mk\fP is .di ZV .in 0 .nf \fC csp_UHOSTS = root@a root@b include caspar/mk/caspar\&.mk .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR The file \fIphp/include/install\&.mk\fP is the same\&. The files \fIgrub/include/install\&.mk\fP and \fIlogrotate/include/install\&.mk\fP are .di ZV .in 0 .nf \fC csp_UHOSTS = root@d root@e root@f root@g include caspar/mk/caspar\&.mk .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR The file \fInrpe/include/install\&.mk\fP is .di ZV .in 0 .nf \fC csp_UHOSTS = root@d root@e root@f root@n include caspar/mk/caspar\&.mk .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR The toplevel \fIMakefile\fP is .di ZV .in 0 .nf \fC dirs = $(patsubst %/Makefile,%,$(shell find * -mindepth 1 -name Makefile)) all: for i in $(dirs); do $(MAKE) -$(MAKEFLAGS) -C $$i; done install for i in $(dirs); do $(MAKE) -$(MAKEFLAGS) -C $$i install; done load for i in $(dirs); do $(MAKE) -$(MAKEFLAGS) -C $$i load; done .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR (we don\&'t feel like sticking a \fIMakefile\fP in all non-leaf nodes of our tree)\&. Now, when running "\fCcsp_UHOSTS_SUBSET=\&'root@e root@f root@m root@n\&' make\fP" in the toplevel, caspar just takes the intersection of csp_UHOSTS_SUBSET and csp_UHOSTS for each csp_UHOSTS list\&. So, caspar will not push anything for \fIapache/\fP and \fIphp/\fP\&. The files \fIgrub/boot/grub/menu\&.lst\fP and \fIlogrotate/etc/logrotate\&.conf\fP will get pushed to \fCroot@e\fP and \fCroot@f\fP only\&. The file \fInrpe/debian/etc/default/nagios-nrpe-server\fP will get pushed to \fCroot@e\fP, \fCroot@f\fP and \fCroot@n\fP\&. This is often better than just overriding csp_UHOSTS on the commandline (or in your shell\&'s environment): if the intersection of the original csp_UHOSTS and your new csp_UHOSTS is empty, chances are big you\&'ve just forgotten to clean your environment\&. \fBCreating remote directories if needed\fP .br \fIMakefile\fP is .di ZV .in 0 .nf \fC csp_DIR = /some/dir/ectory/ csp_PUSH = $(csp_scpmkdir_FUNC) csp_UHOST = root@some\&.host\&.somewhere include caspar/mk/caspar\&.mk .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR Now, before calling scp, caspar will run \&'mkdir -p\&' to create any missing remote directories\&. \fBUsing csp_CP and csp_LOAD\fP .br \fIusername/etc/Makefile\fP is .di ZV .in 0 .nf \fC csp_UHOST = dummy csp_PUSH = $(csp_cp_FUNC) csp_DIR = $(HOME)/etc/ csp_LOAD = crontab-load include \&.\&./include/install\&.mk crontab-load = crontab $(csp_DIR)/crontab .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR while \fI\&.\&./include/install\&.mk\fP is just .di ZV .in 0 .nf \fC include caspar/mk/caspar\&.mk .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR \&. Setting \fCcsp_PUSH\fP to \fC$(csp_cp_FUNC)\fP causes cp(1) to get executed by "make install" (not scp(1))\&. Setting \fCcsp_LOAD\fP causes "make load" to execute the crontab command\&. Just running "make" is OK too, since "make" calls both "make install" and "make load"\&. \fBUsing csp_DIR, csp_LOAD and install(1)\fP .br To install a file on the local host, create e\&.g\&. a file \fIetc/uruk/Makefile\fP like: .di ZV .in 0 .nf \fC csp_UHOST = dummy csp_DIR = /etc/uruk/ csp_PUSH = $(csp_install_FUNC) csp_LOAD = uruk-load include caspar/mk/caspar\&.mk uruk-load = sudo invoke-rc\&.d uruk force-reload .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR \fBUsing csp_DIR and csp_LOAD, take 2\fP .br \fIetc/Makefile\fP is .di ZV .in 0 .nf \fC csp_DIR = /etc/ csp_LOAD = aliases-load include \&.\&./include/install\&.mk aliases-load = $(csp_SSH) $1 "cd /etc && postalias aliases; postfix reload" .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR while \fI\&.\&./include/install\&.mk\fP is .di ZV .in 0 .nf \fC csp_UHOST = root@some\&.host\&.somewhere include caspar/mk/caspar\&.mk .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR \fBBuilding files locally\fP .br Note: csp_BUILD is deprecated\&. You should not use it\&. If you\&'d like to build some files locally from local sources, before installing the just built files, do e\&.g\&.: .di ZV .in 0 .nf \fC csp_UHOST = root@some\&.host\&.somewhere csp_DIR = /etc/ csp_EXTRAFILES = sshd_config csp_TABOOFILES_ADD = sshd_config\&.m4 include caspar/mk/caspar\&.mk sshd_config: sshd_config\&.m4 m4 $< > $@ .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR List all source files in csp_TABOOFILES_ADD: this way, they won\&'t get installed on the csp_UHOST\&. \fBUsing csp_sucp_FUNC and csp_LOAD\fP .br If you\&'d like to use csp_sucp and want a \&`load\&' target, do something like: .di ZV .in 0 .nf \fC csp_PUSH = $(csp_sucp_FUNC) csp_UHOST = foobar\&.example\&.com csp_DIR = /etc/uruk/ csp_LOAD = rc-load include caspar/mk/caspar\&.mk rc-load = $(csp_SSH) $1 sudo invoke-rc\&.d uruk force-reload .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR \fBUsing the "verify" target\fP .br If you want to do some syntax check on the local host for a configuration file, define a -verify target (or pattern target): .di ZV .in 0 .nf \fC bar\&.pem-verify: bar\&.pem\&.asc bar\&.pem gpg --verify $^ %\&.php-verify: %\&.php php -l $< .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR This command will be invoked when you "make verify" and "make install"\&. \fBUsing the "check" target\fP .br If you want to do some syntax check on the remote host, before loading the just installed configuration file, do .di ZV .in 0 .nf \fC csp_UHOST = foobar\&.example\&.com csp_DIR = /etc/ csp_LOAD = my-load csp_CHECK = my-check my-check = $(csp_SSH) $1 do-check-stuff my-load = $(csp_SSH) $1 do-load-stuff include caspar/mk/caspar\&.mk .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR This way, "make load" won\&'t cause the file to load if the check fails (which is probably what you want)\&. You could even give the file a temporary name and have the load target rename it to its real name only after a successful check\&. As a convenience, if a foo-check variable is defined, it is automatically added as a dependency for any csp_LOAD targets named foo or foo-something\&. \fBCombining the csp_LOAD target with multiple hosts; building files remotely\fP .br Here\&'s an example doing some preprocessing on the remote hosts before reloading the configuration: .di ZV .in 0 .nf \fC csp_DIR = /etc/ssh/ csp_UHOSTS = root@some\&.host\&.somewhere root@some\&.other\&.host csp_LOAD = sshd_config-load sshd_config-load = $(csp_SSH) $1 "set -e; \e cd $(csp_DIR); \e m4 sshd_config\&.m4 >sshd_config; \e service ssh reload" include caspar/mk/caspar\&.mk .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR (The old, deprecated way is to explicitly specify the loop over the hosts: .di ZV .in 0 .nf \fC csp_DIR = /etc/ssh/ sshd_config-load: for suh in $(csp_UHOSTS); do \e $(csp_SSH) $$suh "set -e; cd $(csp_DIR); \e m4 sshd_config\&.m4 > sshd_config; \e service ssh reload"; \e done .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR \&. You should not use this method\&. Please consider rewriting any existing caspar snippets using the simpler method described above\&.) \fBUsing the csp_TABOOFILES_{ADD,SKIP} variables; another way to perform remote builds\fP .br Using the csp_TABOOFILES_{ADD,SKIP} variables is handy if you want to \fIinstall\fP a \fIMakefile\fP, instead of using it: Create \fIMakefile\fP just as you\&'d like to have it installed on the remote location\&. Now, create \fIGNUmakefile\fP as e\&.g\&. .di ZV .in 0 .nf \fC csp_TABOOFILES_SKIP = Makefile csp_TABOOFILES_ADD = GNUmakefile csp_DIR = /etc/foobar/ csp_UHOST = root@some\&.host\&.somewhere include caspar/mk/caspar\&.mk load: $(csp_SSH) $(csp_UHOST) "make -C $(csp_DIR)" .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR Now, \fCmake install\fP and \fCmake load\fP will do the right thing\&. \fBUsing the csp_EXTRAFILES variable\fP .br Using the csp_EXTRAFILES variable can be handy if you want to install files with a leading dot\&. E\&.g\&.: .di ZV .in 0 .nf \fC csp_EXTRAFILES = \&.bashrc csp_UHOST = root@some\&.host\&.somewhere csp_DIR = include caspar/mk/caspar\&.mk .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR \fBOverriding csp_UHOSTS\fP .br Supply e\&.g\&. .di ZV .in 0 .nf \fC csp_UHOSTS = root@localhost root@some\&.host\&.somewhere .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR in \fIinstall\&.mk\fP, to install on multiple hosts\&. Run .di ZV .in 0 .nf \fC make filename-install csp_UHOSTS=joe@otherhost .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR to install filename as \fCjoe@otherhost\fP, instead of the default as given in \fIinstall\&.mk\fP\&. If you want to enable passing csp_UHOSTS as a shell environment variable, you\&'ll have to use conditional assignment in your Makefile: .di ZV .in 0 .nf \fC csp_UHOSTS ?= root@localhost root@some\&.host\&.somewhere .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR This allows it to run .di ZV .in 0 .nf \fC % export csp_UHOSTS=foo@bar % make filename-install .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR to install on \fCfoo@bar\fP\&. \fBUsing sudo locally for installing files\fP .br If you\&'d like to install files like .di ZV .in 0 .nf \fC sudo cp foo\&.rc /etc/foobar/ .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR you could set up your \fIMakefile\fP as .di ZV .in 0 .nf \fC csp_DIR = /etc/foobar/ csp_UHOST = dummy csp_PUSH = sudo cp $(1) $(3) include caspar/mk/caspar\&.mk .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR This is like csp_sucp, but without the ssh wrapping: it works on localhost only\&. \fBPlugging your own install script in caspar\fP .br If your script \fCfoobar\fP should be called as e\&.g\&. .di ZV .in 0 .nf \fC foobar --file=fstab --user@host=joe@some\&.host \e --dir=/etc/ --debuglevel=3 .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR then make sure your \fIMakefile\fP features something like .di ZV .in 0 .nf \fC csp_foobar_FUNC = foobar --file=$(1) --user@host=$(2) \e --dir=$(3) --debuglevel=$(4) csp_PUSH = $(csp_foobar_FUNC) csp_XARG = 3 .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR You can now use \fCcsp_UHOST\fP and \fCcsp_DIR\fP just as you\&'re used to\&. \fBMore advanced tricks\fP .br When you don\&'t want to ssh to \fCroot@some\&.host\&.somewhere\fP directly, you could do .di ZV .in 0 .nf \fC sudo rsync -az /path/to/your/config_archive /etc .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR on some\&.host\&.somewhere (e\&.g\&. from cron)\&. .SH FILES \fIcaspar/mk/caspar\&.mk\fP, \fIcaspar/mk/docbook\&.mk\fP, \fIcaspar/mk/pod\&.mk\fP .SH ENVIRONMENT For \fIcaspar\&.mk\fP: \fCcsp_CP\fP, \fCcsp_LOAD\fP, \fCcsp_SCP\fP, \fCcsp_UHOST\fP, \fCcsp_PUSH\fP, \&.\&.\&. .SH BUGS Very likely, GNU Make is not the best tool for doing the stuff \fIcaspar\&.mk\fP is doing\&. For the list of reported bugs, see http://bugs\&.debian\&.org/src:caspar\&. See also TODO, distributed with the caspar package\&. (And online at http://mdcc\&.cx/pub/caspar/caspar-latest/TODO\&.) .SH TRIVIA Caspar is named after Caspar the Friendly Ghost, since that\&'s the title of the Daniel Johnston song I was listening to when deciding to package my homegrown scripts\&. .SH AUTHOR Joost van Baal-Ilić .SH SEE ALSO \fBcaspar-typesetting(7)\fP \fBcsp_helper(1)\fP The caspar homepage is at http://mdcc\&.cx/caspar/ \&. The document \fI"Versiebeheer en software-packages: Waarom en Hoe"\fP (in Dutch) describes some of the reasons why people might want to use tools like caspar\&. Jeroen Hoppenbrouwers blogs about the way he uses caspar, in \fI"Using Subversion and Caspar to maintain a Linux host"\fP\&. Lots of tools overlap (partly) with caspar in their functionality\&. Here\&'s a list\&. ansible (http://www\&.ansible\&.com/); code is on github (https://github\&.com/ansible/ansible) cfengine (http://www\&.cfengine\&.org/), by Mark Burgess e\&.a\&., builds expert systems to administrate and configure large computer networks: it delivers a very big superset of caspar\&'s installation mechanism\&. Puppet (http://reductivelabs\&.com/projects/puppet), also something like a configuration management system\&. Here\&'s an older list; a big part of it was collected by Ray Miller (http://users\&.ox\&.ac\&.uk/~raym/) of Oxford University, and published in the article "Configuration Management with Subversion, YAML and Perl Template Toolkit" in the SANE 2006 (http://www\&.sane\&.nl/sane2006/) conference proceedings\&. FIXME: Check urls, update docbookmk, by Michael Wiedmann (http://www\&.miwie\&.org/docbkmake/) offers probably a superset of Caspar\&'s \fIdocbook\&.mk\fP functionality\&. latex-make by the LaTeX Utils project on http://gforge\&.inria\&.fr/projects/latex-utils/ seems to provide similar functionality as \fIdocbook\&.mk\fP for LaTeX documents\&. Latexmk by John Collins e\&.a\&. on http://www\&.phys\&.psu\&.edu/~collins/software/latexmk-jcc/ is another implementation of this idea\&. SUP, the Software Upgrade Protocol and it\&'s implementation by Carnegie Mellon University offers another way to distribute (configuration)files\&. Beware though: between Nov 1996 and June 2004, no new release has been published\&. The Debian (ftp://ftp\&.debian\&.org/debian/pool/main/s/sup/) and NetBSD packages are likely still maintained, though\&. PIKT (http://www\&.pikt\&.org/) is intended primarily for system monitoring, but does do configuration management too\&. LCFG (http://www\&.lcfg\&.org/) is another configuration management system\&. The Arusha Project (ARK, at http://ark\&.sf\&.net/) provides a framework for collaborative system administration\&. Bcfg2 (http://trac\&.mcs\&.anl\&.gov/projects/bcfg2/) is yet another configuration management system\&. quattor (http://quattor\&.web\&.cern\&.ch/) is a system administration toolkit for installation, configuration and management of Unix systems\&. rb3 and friends, as written and used by Ray Miller e\&.a\&. at Oxford University, (http://users\&.ox\&.ac\&.uk/~raym/software/configuration-management/)\&. The \fIsvk\fP version control system is said to be quite usable for handling configuration file management (without a separate install mechanism like caspar)\&. See also \fIthis discussion on the Debian development list\fP\&. On the http://www\&.infrastructures\&.org/ website on automated (Unix) system administration, you can find some thoughts on managing configuration files using a version control system\&.