<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <!-- Copyright (c) 2012 Joost van Baal-Ilić --> <head> <meta name="keywords" content="manual"> <style type="text/css"> /* START aephea.base.css */ body { text-align: justify; margin-left: 0%; margin-right: 0%; } a:link { text-decoration: none; } a:active { text-decoration: none; } a:visited { text-decoration: none; } a:link { color: #1111aa; } a:active { color: #1111aa; } a:visited { color: #111166; } a.local:link { color: #11aa11; } a.local:active { color: #11aa11; } a.local:visited { color: #116611; } a.intern:link { color: #1111aa; } a.intern:active { color: #1111aa; } a.intern:visited { color: #111166; } a.extern:link { color: #aa1111; } a.extern:active { color: #aa1111; } a.extern:visited { color: #661111; } a.quiet:link { color: black; } a.quiet:active { color: black; } a.quiet:visited { color: black; } div.verbatim { font-family: monospace; margin-top: 1em; margin-bottom: 1em; font-size: 10pt; margin-left: 2em; white-space: pre; } div.indent { margin-left: 8%; margin-right: 0%; } .right { text-align: right; } .left { text-align: left; } .nowrap { white-space: nowrap; } .item_leader { position: relative; margin-left: 8%; } .item_compact { position: absolute; vertical-align: baseline; } .item_cascade { position: relative; } .item_leftalign { text-align: left; } .item_rightalign { width: 2em; text-align: right; } .item_compact .item_rightalign { position: absolute; width: 52em; right: -2em; text-align: right; } .item_text { position: relative; margin-left: 3em; } .smallcaps { font-size: smaller; text-transform: uppercase } /* END aephea.base.css */ body { font-family: "Garamond", "Gill Sans", "Verdana", sans-serif; } body { text-align: justify; margin-left: 8%; margin-right: 8%; } </style> <title>caspar</title> </head> <body> <p style="text-align:right"> 8 mai 2012 <a class="local" href="caspar.ps"><b>caspar</b></a> 20120508 </p> <div class=" itemize " style="margin-top:1em; font-size:100%"> <div class=" item_compact"><div class=" item_rightalign nowrap " style="right:-3em">1.</div></div> <div class=" item_text " style="margin-left:4em"> <a class="intern" href="#name">NAME</a> </div> <div class=" item_compact"><div class=" item_rightalign nowrap " style="right:-3em">2.</div></div> <div class=" item_text " style="margin-left:4em"> <a class="intern" href="#synopsis">SYNOPSIS</a> </div> <div class=" item_compact"><div class=" item_rightalign nowrap " style="right:-3em">3.</div></div> <div class=" item_text " style="margin-left:4em"> <a class="intern" href="#description">DESCRIPTION</a> </div> <div class=" item_compact"><div class=" item_rightalign nowrap " style="right:-3em">4.</div></div> <div class=" item_text " style="margin-left:4em"> <a class="intern" href="#usage">USAGE</a> </div> <div class=" item_compact"><div class=" item_rightalign nowrap " style="right:-3em">5.</div></div> <div class=" item_text " style="margin-left:4em"> <a class="intern" href="#variables">VARIABLES</a> </div> <div class=" item_compact"><div class=" item_rightalign nowrap " style="right:-3em">6.</div></div> <div class=" item_text " style="margin-left:4em"> <a class="intern" href="#examples">EXAMPLES</a> </div> <div class=" item_compact"><div class=" item_rightalign nowrap " style="right:-3em">7.</div></div> <div class=" item_text " style="margin-left:4em"> <a class="intern" href="#files">FILES</a> </div> <div class=" item_compact"><div class=" item_rightalign nowrap " style="right:-3em">8.</div></div> <div class=" item_text " style="margin-left:4em"> <a class="intern" href="#environment">ENVIRONMENT</a> </div> <div class=" item_compact"><div class=" item_rightalign nowrap " style="right:-3em">9.</div></div> <div class=" item_text " style="margin-left:4em"> <a class="intern" href="#bugs">BUGS</a> </div> <div class=" item_compact"><div class=" item_rightalign nowrap " style="right:-3em">10.</div></div> <div class=" item_text " style="margin-left:4em"> <a class="intern" href="#trivia">TRIVIA</a> </div> <div class=" item_compact"><div class=" item_rightalign nowrap " style="right:-3em">11.</div></div> <div class=" item_text " style="margin-left:4em"> <a class="intern" href="#author">AUTHOR</a> </div> <div class=" item_compact"><div class=" item_rightalign nowrap " style="right:-3em">12.</div></div> <div class=" item_text " style="margin-left:4em"> <a class="intern" href="#seealso">SEE ALSO</a> </div> </div> <a name="name"></a> <h2>NAME</h2> caspar - Makefile snippets for common tasks <a name="synopsis"></a> <h2>SYNOPSIS</h2> In a Makefile, write either <div class="verbatim"> include caspar/mk/caspar.mk </div> or <div class="verbatim"> include caspar/mk/docbook.mk </div> or <div class="verbatim"> include caspar/mk/pod.mk </div> . <a name="description"></a> <h2>DESCRIPTION</h2> Caspar offers Makefile snippets for common tasks, like installing (configuration) files, or typesetting LaTeX, DocBook XML and DocBook SGML documents. <p style="margin-bottom:0" class="asd_par"> The typesetting functionality is delivered by <i>docbook.mk</i> and <i>pod.mk</i>. This is documented in <a class="local sibling" href="caspar-typesetting.html">caspar-typesetting(7)</a>. </p> <p style="margin-bottom:0" class="asd_par"> The installing-stuff functionality is delivered by <i>caspar.mk</i>. (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). </p> <p style="margin-bottom:0" class="asd_par"> 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. </p> <p style="margin-bottom:0" class="asd_par"> With <b>caspar</b>, all you have to do is specify the hostname in one place, and specify the name of the target directory in each CVS directory. </p> <p style="margin-bottom:0" class="asd_par"> 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. </p> <a name="usage"></a> <h2>USAGE</h2> Within a CVS tree, create a file <i>include/install.mk</i>, with contents like e.g. <div class="verbatim"> csp_UHOST = root@some.host.somewhere include caspar/mk/caspar.mk </div> . Within each other directory of the CVS tree which holds files, create a Makefile, which looks like e.g. <div class="verbatim"> csp_DIR = /some/dir/ectory/ include ../../include/install.mk </div> . If you'd like to use the <i>install-recursive</i> target too, in directories which hold subdirectories (but not files), you'll have to create a Makefile which looks something like <div class="verbatim"> include ../../include/install.mk </div> . From within the CVS tree, one can call: <div class="verbatim"> make <filename>-install make install make load make make install-recursive </div> Calling <tt>make install</tt> (or <tt>make</tt>) now will scp all files in the current directory to the remote location. The <i>install-recursive</i> target descends down the tree, and calls <tt>make install</tt> in each subdirectory. <p style="margin-bottom:0" class="asd_par"> 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 <tt>csp_UHOST = root@some.host.somewhere</tt>). If you don't like this, and would like to have a <tt>PermitRootLogin no</tt> in your <tt>/etc/ssh/sshd_config</tt>, you can use csp_sucp(1). See below. </p> <a name="variables"></a> <h2>VARIABLES</h2> <p style="margin-bottom:0" class="asd_par"> The variables one can set in a calling Makefile are: <div class=" itemize " style="margin-top:1em; font-size:100%"> <div class=" item_cascade"><div class=" item_leftalign nowrap " ><tt>csp_UHOST</tt></div></div> <div class=" item_text " style="margin-left:2em"> user@host, reachable using <tt>$(csp_PUSH)</tt> (which is scp by default) </div> <div class=" item_cascade"><div class=" item_leftalign nowrap " ><tt>csp_UHOSTS</tt></div></div> <div class=" item_text " style="margin-left:2em"> space separated list of user@host items, reachable using <tt>$(csp_PUSH)</tt> </div> <div class=" item_cascade"><div class=" item_leftalign nowrap " ><tt>csp_DIR</tt></div></div> <div class=" item_text " style="margin-left:2em"> directory on host, reachable using function <tt>$(csp_PUSH)</tt> </div> <div class=" item_cascade"><div class=" item_leftalign nowrap " ><tt>csp_PUSH</tt></div></div> <div class=" item_text " style="margin-left:2em"> 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: <i>[user@]host</i>, remote <i>directory</i> and local <i>filename</i>. <i>[user@]host</i> will be set to all elements of <tt>$(csp_UHOSTS)</tt>; <i>directory</i> will be set to <tt>$(csp_DIR)</tt>. Currently, <tt>$(csp_scp_FUNC)</tt>, <tt>$(csp_cp_FUNC)</tt> and <tt>$(csp_sucp_FUNC)</tt> are supported as push plugins. If <tt>csp_PUSH</tt> is unset, the default <tt>$(csp_scp_FUNC)</tt> is used. </div> <div class=" item_cascade"><div class=" item_leftalign nowrap " ><tt>csp_LOAD</tt></div></div> <div class=" item_text " style="margin-left:2em"> targets which should depend on the `load' target. </div> <div class=" item_cascade"><div class=" item_leftalign nowrap " ><tt>csp_BUILD</tt></div></div> <div class=" item_text " style="margin-left:2em"> targets which should depend on the `build' target. </div> <div class=" item_cascade"><div class=" item_leftalign nowrap " ><tt>csp_CP</tt></div></div> <div class=" item_text " style="margin-left:2em"> cp binary, just "cp" by default </div> <div class=" item_cascade"><div class=" item_leftalign nowrap " ><tt>csp_SCP</tt></div></div> <div class=" item_text " style="margin-left:2em"> scp binary, just "scp" by default </div> <div class=" item_cascade"><div class=" item_leftalign nowrap " ><tt>csp_SUCP</tt></div></div> <div class=" item_text " style="margin-left:2em"> script wrapping sudo in ssh, "csp_sucp" by default </div> <div class=" item_cascade"><div class=" item_leftalign nowrap " ><tt>csp_EXTRAFILES</tt></div></div> <div class=" item_text " style="margin-left:2em"> extra files which should be installed. Can be used to include files starting with a dot. </div> <div class=" item_cascade"><div class=" item_leftalign nowrap " ><tt>csp_TABOOFILES</tt></div></div> <div class=" item_text " style="margin-left:2em"> files which should never be installed. Set to <tt>Makefile .%.swp %~ #%# pod2htmd.tmp pod2htmi.tmp</tt> by default. </div> <div class=" item_cascade"><div class=" item_leftalign nowrap " ><tt>csp_TABOOFILES_ADD</tt></div></div> <div class=" item_text " style="margin-left:2em"> extra files which should never be installed; added to list in <tt>csp_TABOOFILES</tt>. </div> <div class=" item_cascade"><div class=" item_leftalign nowrap " ><tt>csp_TABOOFILES_SKIP</tt></div></div> <div class=" item_text " style="margin-left:2em"> files which should be installed, even if in initial <tt>csp_TABOOFILES</tt> list. Removed from <tt>csp_TABOOFILES</tt> list. </div> <div class=" item_cascade"><div class=" item_leftalign nowrap " ><tt>csp_TABOODIRS</tt></div></div> <div class=" item_text " style="margin-left:2em"> directories to exclude in install-recursive target. set to <tt>CVS .svn</tt> by default. </div> <div class=" item_cascade"><div class=" item_leftalign nowrap " ><tt>csp_TABOODIRS_ADD</tt>, <tt>csp_TABOODIRS_SKIP</tt></div></div> <div class=" item_text " style="margin-left:2em"> see <tt>csp_TABOOFILES</tt> equivalents. </div> <div class=" item_cascade"><div class=" item_leftalign nowrap " ><tt>csp_UHOSTS_SUBSET</tt></div></div> <div class=" item_text " style="margin-left:2em"> 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. </div> </div> </p> <p style="margin-bottom:0" class="asd_par"> The following variables might get phased out or removed soonish: <div class=" itemize " style="margin-top:1em; font-size:100%"> <div class=" item_cascade"><div class=" item_leftalign nowrap " ><tt>csp_CPFLAGS</tt></div></div> <div class=" item_text " style="margin-left:2em"> extra arguments to pass to cp invocation, none by default </div> <div class=" item_cascade"><div class=" item_leftalign nowrap " ><tt>csp_SCPFLAGS</tt></div></div> <div class=" item_text " style="margin-left:2em"> extra arguments to pass to scp invocation, e.g. '<tt>-i .ssh/id_rsa-root</tt>' </div> </div> </p> <a name="examples"></a> <h2>EXAMPLES</h2> <p style="margin-bottom:0" class="asd_par"> Some examples: </p> <p style="margin-bottom:0"><b>Using csp_UHOST</b><br> This is the simplest way to use caspar. <i>Makefile</i> is <div class="verbatim"> csp_UHOST = root@some.host.somewhere csp_DIR = /etc/ include caspar/mk/caspar.mk </div> Now, running "make" will scp all files in the current directory to <tt>root@some.host.somewhere:/etc/</tt>. </p> <p style="margin-bottom:0"><b>More hosts, not scp but sudo via ssh: using csp_PUSH</b><br> <i>Makefile</i> is <div class="verbatim"> csp_UHOSTS = root@some.host.somewhere root@some.other.host csp_PUSH = $(csp_sucp_FUNC) csp_DIR = /etc/ include caspar/mk/caspar.mk </div> 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 <tt>fstab</tt> 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 <div class="verbatim"> csp_XARG = postgres </div> . (If such a username is not supplied, sudo (and csp_sucp) use the default: root.) </p> <p style="margin-bottom:0"><b>Overriding csp_UHOSTS: csp_UHOSTS_SKIP</b><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: <div class="verbatim"> % 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/ </div> </p> <p style="margin-bottom:0"><b>Overriding csp_UHOSTS in a smart way: csp_UHOSTS_SUBSET. Using multiple groups of hosts. Recursive make made easy.</b><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 <div class="verbatim"> 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 </div> The file <i>apache/etc/apache2/Makefile</i> is: <div class="verbatim"> csp_DIR = /etc/apache2/ include ../../include/install.mk </div> (all other <i>Makefile</i>s are similar). The file <i>apache/include/install.mk</i> is <div class="verbatim"> csp_UHOSTS = root@a root@b include caspar/mk/caspar.mk </div> The file <i>php/include/install.mk</i> is the same. The files <i>grub/include/install.mk</i> and <i>logrotate/include/install.mk</i> are <div class="verbatim"> csp_UHOSTS = root@d root@e root@f root@g include caspar/mk/caspar.mk </div> The file <i>nrpe/include/install.mk</i> is <div class="verbatim"> csp_UHOSTS = root@d root@e root@f root@n include caspar/mk/caspar.mk </div> The toplevel <i>Makefile</i> is <div class="verbatim"> 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 </div> (we don't feel like sticking a <i>Makefile</i> in all non-leaf nodes of our tree). </p> <p style="margin-bottom:0" class="asd_par"> Now, when running "<tt>csp_UHOSTS_SUBSET='root@e root@f root@m root@n' make</tt>" 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 <i>apache/</i> and <i>php/</i>. The files <i>grub/boot/grub/menu.lst</i> and <i>logrotate/etc/logrotate.conf</i> will get pushed to <tt>root@e</tt> and <tt>root@f</tt> only. The file <i>nrpe/debian/etc/default/nagios-nrpe-server</i> will get pushed to <tt>root@e</tt>, <tt>root@f</tt> and <tt>root@n</tt>. </p> <p style="margin-bottom:0" class="asd_par"> 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. </p> <p style="margin-bottom:0"><b>Creating remote directories if needed</b><br> <i>Makefile</i> is <div class="verbatim"> csp_DIR = /some/dir/ectory/ csp_PUSH = $(csp_scpmkdir_FUNC) csp_UHOST = root@some.host.somewhere include caspar/mk/caspar.mk </div> Now, before calling scp, caspar will run 'mkdir -p' to create any missing remote directories. </p> <p style="margin-bottom:0"><b>Using csp_CP and csp_LOAD</b><br> <i>username/etc/Makefile</i> is <div class="verbatim"> 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 </div> while <i>../include/install.mk</i> is just <div class="verbatim"> include caspar/mk/caspar.mk </div> . Setting <tt>csp_PUSH</tt> to <tt>$(csp_cp_FUNC)</tt> causes cp(1) to get executed by "make install" (not scp(1)). Setting <tt>csp_LOAD</tt> causes "make load" to execute the crontab command. Just running "make" is OK too, since "make" calls both "make install" and "make load". </p> <p style="margin-bottom:0"><b>Using csp_DIR, csp_LOAD and install(1)</b><br> To install a file on the local host, create e.g. a file <i>etc/uruk/Makefile</i> like: <div class="verbatim"> 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 </div> </p> <p style="margin-bottom:0"><b>Using csp_DIR and csp_LOAD, take 2</b><br> <i>etc/Makefile</i> is <div class="verbatim"> csp_DIR = /etc/ csp_LOAD = aliases-load include ../include/install.mk aliases-load: $(csp_SSH) $(csp_UHOST) "cd /etc; postalias aliases; postfix reload" </div> while <i>../include/install.mk</i> is <div class="verbatim"> csp_UHOST = root@some.host.somewhere include caspar/mk/caspar.mk </div> </p> <p style="margin-bottom:0"><b>Using csp_BUILD: building files locally</b><br> If you'd like to build some files locally from local sources, before installing the just build files, do e.g. <div class="verbatim"> csp_UHOST = root@some.host.somewhere csp_DIR = /etc/ csp_TABOOFILES_ADD = sshd_config.m4 csp_BUILD = my-build include caspar/mk/caspar.mk my-build: sshd_config sshd_config: sshd_config.m4 m4 $< > $@ </div> List all source files in csp_TABOOFILES_ADD: this way, they won't get installed on the csp_UHOST. </p> <p style="margin-bottom:0"><b>Using csp_sucp_FUNC and csp_LOAD</b><br> If you'd like to use csp_sucp and want a `load' target, do something like: <div class="verbatim"> 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) $(csp_UHOST) "sudo invoke-rc.d uruk force-reload" </div> </p> <p style="margin-bottom:0"><b>Adding a "check" target</b><br> If you want to do some syntax check on the remote host, before loading the just installed configuration file (and have a "make check" thing), do <div class="verbatim"> csp_UHOST = foobar.example.com csp_DIR = /etc/ csp_LOAD = check my-load include caspar/mk/caspar.mk check: $(csp_SSH) $(csp_UHOST) do-check-stuff my-load: $(csp_SSH) $(csp_UHOST) do-load-stuff </div> This way, "make load" won't cause the file to load if the check fails (which is probably what you want). Running "make" will perform "install", "check" and "load". </p> <p style="margin-bottom:0"><b>Combining the csp_LOAD target with multiple hosts; building files remotely</b><br> You'll have to loop over csp_UHOSTS to execute load-command. Here's an example doing some preprocessing on the remote hosts too. <div class="verbatim"> csp_DIR = /etc/ssh/ csp_UHOSTS = root@some.host.somewhere root@some.other.host csp_LOAD = sshd_config-load sshd_config-load = ssh $1 "cd $(csp_DIR); \ m4 sshd_config.m4 >sshd_config && \ PATH=$$PATH:/sbin /etc/init.d/ssh restart" include caspar/mk/caspar.mk </div> (Alternatively, you could explicitly specify the loop over the hosts: <div class="verbatim"> csp_DIR = /etc/ssh/ sshd_config-load: for suh in $(csp_UHOSTS); do \ ssh $$suh "cd $(csp_DIR); \ m4 sshd_config.m4 > sshd_config && \ PATH=$$PATH:/sbin /etc/init.d/ssh restart"; \ done </div> ). </p> <p style="margin-bottom:0"><b>Using the csp_TABOOFILES_{ADD,SKIP} variables; another way to perform remote builds</b><br> Using the csp_TABOOFILES_{ADD,SKIP} variables is handy if you want to <i>install</i> a <i>Makefile</i>, instead of using it: Create <i>Makefile</i> just as you'd like to have it installed on the remote location. Now, create <i>GNUmakefile</i> as e.g. <div class="verbatim"> 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)" </div> Now, <tt>make install</tt> and <tt>make load</tt> will do the right thing. </p> <p style="margin-bottom:0"><b>Using the csp_EXTRAFILES variable</b><br> Using the csp_EXTRAFILES variable is handy if you want to install files with a leading dot. E.g.: <div class="verbatim"> csp_EXTRAFILES = .bashrc csp_UHOST = root@some.host.somewhere csp_DIR = include caspar/mk/caspar.mk </div> </p> <p style="margin-bottom:0"><b>Overriding csp_UHOSTS</b><br> Supply e.g. <div class="verbatim"> csp_UHOSTS = root@localhost root@some.host.somewhere </div> in <i>install.mk</i>, to install on multiple hosts. Run <div class="verbatim"> make filename-install csp_UHOSTS=joe@otherhost </div> to install filename as <tt>joe@otherhost</tt>, instead of the default as given in <i>install.mk</i>. If you want to enable passing csp_UHOSTS as a shell environment variable, you'll have to use conditional assignment in your Makefile: <div class="verbatim"> csp_UHOSTS ?= root@localhost root@some.host.somewhere </div> This allows it to run <div class="verbatim"> % export csp_UHOSTS=foo@bar % make filename-install </div> to install on <tt>foo@bar</tt>. </p> <p style="margin-bottom:0"><b>Using sudo locally for installing files</b><br> If you'd like to install files like <div class="verbatim"> sudo cp foo.rc /etc/foobar/ </div> you could set up your <i>Makefile</i> as <div class="verbatim"> csp_DIR = /etc/foobar/ csp_UHOST = dummy csp_PUSH = sudo cp $(1) $(3) include caspar/mk/caspar.mk </div> This is like csp_sucp, but without the ssh wrapping: it works on localhost only. </p> <p style="margin-bottom:0"><b>Plugging your own install script in caspar</b><br> If your script <tt>foobar</tt> should be called as e.g. <div class="verbatim"> foobar --file=fstab --user@host=joe@some.host \ --dir=/etc/ --debuglevel=3 </div> then make sure your <i>Makefile</i> features something like <div class="verbatim"> csp_foobar_FUNC = foobar --file=$(1) --user@host=$(2) \ --dir=$(3) --debuglevel=$(4) csp_PUSH = $(csp_foobar_FUNC) csp_XARG = 3 </div> You can now use <tt>csp_UHOST</tt> and <tt>csp_DIR</tt> just as you're used to. </p> <p style="margin-bottom:0"><b>More advanced tricks</b><br> When you don't want to ssh to <tt>root@some.host.somewhere</tt> directly, you could do <div class="verbatim"> sudo rsync -az /path/to/your/config_archive /etc </div> on some.host.somewhere (e.g. from cron). </p> <a name="files"></a> <h2>FILES</h2> <i>caspar/mk/caspar.mk</i>, <i>caspar/mk/docbook.mk</i>, <i>caspar/mk/pod.mk</i> <a name="environment"></a> <h2>ENVIRONMENT</h2> For <i>caspar.mk</i>: <tt>csp_CP</tt>, <tt>csp_LOAD</tt>, <tt>csp_SCP</tt>, <tt>csp_UHOST</tt>, <tt>csp_PUSH</tt>, ... <a name="bugs"></a> <h2>BUGS</h2> Very likely, GNU Make is not the best tool for doing the stuff <i>caspar.mk</i> is doing. For the list of reported bugs, see <a class="extern" href="http://bugs.debian.org/src:caspar">http://bugs.debian.org/src:caspar</a>. See also TODO, distributed with the caspar package. (And online at <a class="extern" href="http://mdcc.cx/pub/caspar/caspar-latest/TODO">http://mdcc.cx/pub/caspar/caspar-latest/TODO</a>.) <a name="trivia"></a> <h2>TRIVIA</h2> 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. <a name="author"></a> <h2>AUTHOR</h2> Joost van Baal-Ilić <a name="seealso"></a> <h2>SEE ALSO</h2> <a class="local sibling" href="caspar-typesetting.html">caspar-typesetting(7)</a> <a class="local sibling" href="csp_helper.html">csp_helper(1)</a> <p style="margin-bottom:0" class="asd_par"> The caspar homepage is at <a class="extern" href="http://mdcc.cx/caspar/">http://mdcc.cx/caspar/</a> . </p> <p style="margin-bottom:0" class="asd_par"> The document <a target="_parent" class="extern" href="http://non-gnu.uvt.nl/pub/uvt-unix-doc/packaging/">"Versiebeheer en software-packages: Waarom en Hoe"</a> (in Dutch) describes some of the reasons why people might want to use tools like caspar. </p> <p style="margin-bottom:0" class="asd_par"> Jeroen Hoppenbrouwers blogs about the way he uses caspar, in <a target="_parent" class="extern" href="http://www.hoppie.nl/pub/node/79">"Using Subversion and Caspar to maintain a Linux host"</a>. </p> <p style="margin-bottom:0" class="asd_par"> Lots of tools overlap (partly) with caspar in their functionality. Here's a list. A big part of it was collected by Ray Miller (<a class="extern" href="http://users.ox.ac.uk/~raym/">http://users.ox.ac.uk/~raym/</a>) of Oxford University, and published in the article "Configuration Management with Subversion, YAML and Perl Template Toolkit" in the SANE 2006 (<a class="extern" href="http://www.sane.nl/sane2006/">http://www.sane.nl/sane2006/</a>) conference proceedings. FIXME: Check urls, update </p> <p style="margin-bottom:0" class="asd_par"> docbookmk, by Michael Wiedmann (<a class="extern" href="http://www.miwie.org/docbkmake/">http://www.miwie.org/docbkmake/</a>) offers probably a superset of Caspar's <i>docbook.mk</i> functionality. </p> <p style="margin-bottom:0" class="asd_par"> latex-make by the LaTeX Utils project on <a class="extern" href="http://gforge.inria.fr/projects/latex-utils/">http://gforge.inria.fr/projects/latex-utils/</a> seems to provide similar functionality as <i>docbook.mk</i> for LaTeX documents. </p> <p style="margin-bottom:0" class="asd_par"> Latexmk by John Collins e.a. on <a class="extern" href="http://www.phys.psu.edu/~collins/software/latexmk-jcc/">http://www.phys.psu.edu/~collins/software/latexmk-jcc/</a> is another implementation of this idea. </p> <p style="margin-bottom:0" class="asd_par"> 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 (<a class="extern" href="ftp://ftp.debian.org/debian/pool/main/s/sup/">ftp://ftp.debian.org/debian/pool/main/s/sup/</a>) and NetBSD packages are likely still maintained, though. </p> <p style="margin-bottom:0" class="asd_par"> cfengine (<a class="extern" href="http://www.cfengine.org/">http://www.cfengine.org/</a>), 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. </p> <p style="margin-bottom:0" class="asd_par"> PIKT (<a class="extern" href="http://www.pikt.org/">http://www.pikt.org/</a>) is intended primarily for system monitoring, but does do configuration management too. </p> <p style="margin-bottom:0" class="asd_par"> LCFG (<a class="extern" href="http://www.lcfg.org/">http://www.lcfg.org/</a>) is another configuration management system. </p> <p style="margin-bottom:0" class="asd_par"> The Arusha Project (ARK, at <a class="extern" href="http://ark.sf.net/">http://ark.sf.net/</a>) provides a framework for collaborative system administration. </p> <p style="margin-bottom:0" class="asd_par"> Puppet (<a class="extern" href="http://reductivelabs.com/projects/puppet">http://reductivelabs.com/projects/puppet</a>), also something like a configuration management system. </p> <p style="margin-bottom:0" class="asd_par"> Bcfg2 (<a class="extern" href="http://trac.mcs.anl.gov/projects/bcfg2/">http://trac.mcs.anl.gov/projects/bcfg2/</a>) is yet another configuration management system. </p> <p style="margin-bottom:0" class="asd_par"> quattor (<a class="extern" href="http://quattor.web.cern.ch/">http://quattor.web.cern.ch/</a>) is a system administration toolkit for installation, configuration and management of Unix systems. </p> <p style="margin-bottom:0" class="asd_par"> rb3 and friends, as written and used by Ray Miller e.a. at Oxford University, (<a class="extern" href="http://users.ox.ac.uk/~raym/software/configuration-management/">http://users.ox.ac.uk/~raym/software/configuration-management/</a>). </p> <p style="margin-bottom:0" class="asd_par"> The <a target="_parent" class="extern" href="http://svk.elixus.org/">svk</a> version control system is said to be quite usable for handling configuration file management (without a separate install mechanism like caspar). See also <a target="_parent" class="extern" href="http://lists.debian.org/debian-devel/2005/02/thrd2.html#00495">this discussion on the Debian development list</a>. </p> <p style="margin-bottom:0" class="asd_par"> On the <a class="extern" href="http://www.infrastructures.org/">http://www.infrastructures.org/</a> website on automated (Unix) system administration, you can find some thoughts on managing configuration files using a version control system. </p> </body> </html>