pax_global_header00006660000000000000000000000064131246775320014524gustar00rootroot0000000000000052 comment=e91642e1d1215b7c2a6625b7c9c4572ab3530336 metche-1.2.4/000077500000000000000000000000001312467753200127755ustar00rootroot00000000000000metche-1.2.4/Changelog000066400000000000000000000033311312467753200146070ustar00rootroot000000000000001.2.4 (2017 06 28) * Unset LC_COLLATE as well: it affects sorting so "metche report" output for packages changes can be erroneously large when run with locales different from the ones used by cron. 1.2.3 (2017 06 27) * Update URLs: Redmine → Gitlab. * Tell mutt *not* to save outgoing email. This fixes Debian bug #657071. * Bypass root's mutt configuration file. 1.2.2 (2012 06 02) * Ignore changes to $WATCHED_DIR itself. This fixes the dreaded "sometimes sends empty reports" bug metche has had since forever. * Fix GnuPG groups support: check for encryption key existence using gpg --encrypt instead of --list-public-keys. * Spelling and grammar fixes in manpage. 1.2.1 (2011 06 05) * Support more mailers than just mutt. Thanks to Kan-Ru Chen for the preliminary patch. * EXCLUDES: add a bunch of VCS directories. * documentation: add a few Q&A to the FAQ, update website and VCS information. 1.2 (2009 12 16) * stabilize: manual "metche stabilize" invocation and metche first run now send an e-mail (Closes: http://poivron.org/dev/metche/ticket/43) * documentation: tell about GnuPG's "group" option, that allows to encrypt email for multiple recipients. * EXCLUDES: added .cache, everchanging on LVM setup, and ssh private host keys. * configuration: added SEND_STABLE_REPORTS configuration setting that controls whether a report email is sent after saving a stable state; defaults to "yes" for backward compatibility. 1.1 (2006 09 16) * ververs: added Linux VServers support. * EXCLUDES: added a few everchanging Postfix files, and AlternC's local.sh * documentation: clear up the way backups are made (Closes: #365694) 1.0 (2006 02 17) * Initial release. metche-1.2.4/FAQ000066400000000000000000000124721312467753200133350ustar00rootroot00000000000000,------------------------------------------------------------------------------- | Frequently asked questions about metche `------------------------------------------------------------------------------- 1. How are the monitored Changelog files ($CHANGELOG_FILE or $CHANGELOG_DIR/*/Changelog) generated? With Emacs or Vim. They are written by *you*! They are an important part of the collective sysadmin process metche is supposed to simplify. 2. How is metche working, and what are the underlying concepts I have to understand? When called with the cron command line switch, metche verifies changes in the system state during the last $TESTING_TIME minutes. If any changes took place an "unstable state" is saved. Otherwise, a "testing state" is saved and a report is emailed to you. A mechanism exists to automatically turn a "testing state" into a "stable" one. See metche(8) for explanations. 3. How do I see the saved states list? Run "metche list". 4. I've broken my system, how can I see a report against a previous, system state, known as working? Run "metche report [{stable,testing,unstable}-YYYYMMDDHHMM]". If no saved state is specified, the most recently saved "testing state" is used as reference. 5. How do I create a "stable state" manually? Run "metche stabilize [testing-YYYYMMDDHHMM]". This turns the given "testing state", if specified, otherwise the one most recently saved, into a "stable state". 6. Why is metche filling my /var partition? First, metche needs to make backups of your "system state" in order to be able to provide you with changes reports. Whatever you do, metche *will* use some disk space (a few dozens megabytes on a typical server). Please note metche performs full, and not incremental, backups. But there are a few ways to limit the disk space metche uses. Here is the cookbook. a) Exclude some big files from the set monitored by metche. - Have a look to your metche backup files: # ls -l /var/lib/metche/*.tar.bz2 - If the average size for these files is greater than a few megabytes, you should investigate which file or directory (in $WATCHED_DIR) is guilty and use the EXCLUDES option to keep it out of metche's hands. b) Speed up the mechanism that automatically turns an "unstable state" into a "testing state", and a "testing state into a "stable" one. - First, let metche run for a while with its default TESTING_TIME and STABLE_TIME configuration values (the "for a while" meaning depends on how much nervous you get when you run 'df /var' every five minute; a few days is a bare minimum, a few weeks is better). - Then, have a look to the files metche has kept in $BACKUP_DIR; a simple 'metche list' is enough if you're not monitoring any VServer. - If there is a huge list of "unstable" but only few "testing" states, you can try lowering TESTING_TIME. If there are many more "testing" states than "stable" state, you can try lowering STABLE_TIME. It's better to only tweak one of these two parameters at a time. - Let metche run "for a while" again... and iterate. c) Still despaired? If this does not work for you, you might also have found a weird case that metche does not handle well, call it a bug or whatever you want; you should actually e-mail us (metche AT lists DOT riseup DOT net) the output of 'metche list', your configuration file (stripped from private information), and some information about the metche version you're running. 7. metche does not send us any report It could be an e-mail problem, but, more probably, one of your installed programs violates the FHS and writes one or more ever-changing files in /etc instead of /var. This prevents metche of turning any "unstable" state into a "testing" state, and therefore to send you any report. You can diagnose this by asking metche to generate a report against a recent unstable state, such as '# metche report unstable-latest'. If the output contains changed files you don't want to monitor, such as status files, add them to your EXCLUDES option in metche.conf, and wait. 8. metche sends us empty reports The change detection method is quick but not very accurate. E.g. a change to the mtime of a monitored file makes metche think changes need to be reported. In case you are receiving empty reports really often such as once every hour: most probably one of your installed programs frequently changes the ctime or mtime of a file in /etc without actually modifying its content. See the answer to question #7 for details. 9. How do I configure e-mail encryption when sending metche reports to my sysadmin collective? See the SECURITY section of metche(8). You might also be interested in Schleuder (http://schleuder.nadir.org/). 10. Why am I receiving metche reports as attachments with Content-Type: application/octet-stream? You are probably using heirloom-mailx as /usr/bin/mail. That program's charset conversion features depend on the current locale. You may either switch to bsd-mailx or set the LOCALE variable in metche.conf to something better suited than "C" to the charset(s) used in the Changelog and other monitored files. metche-1.2.4/INSTALL000066400000000000000000000006141312467753200140270ustar00rootroot00000000000000,------------------------------------------------------------------------------- | INSTALLATION `------------------------------------------------------------------------------- 1. Have a look at the REQUIREMENTS section in the README file. 2. Copy the metche executable to /usr/local/sbin/ 3. Copy the manpage (metche.8) to /usr/local/man/man8/ 4. Read the README file, the FAQ and the manpage metche-1.2.4/LICENSE000066400000000000000000000431101312467753200140010ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. metche-1.2.4/Makefile000066400000000000000000000006411312467753200144360ustar00rootroot00000000000000all: doc metche.8: metche.8.markdown pandoc --read=markdown --write=man --output=metche.8 --standalone $< doc: metche.8 clean: distclean: clean rm -f metche.8 VERSION=$(shell head -n1 Changelog | awk '{print $$1}') TARBALL=../metche-$(VERSION).tar.gz release: Changelog ! [ -f $(TARBALL) ] git archive \ --prefix=metche-$(VERSION)/ \ --output=$(TARBALL) \ master .PHONY: all doc clean distclean metche-1.2.4/NEWS000066400000000000000000000004041312467753200134720ustar00rootroot00000000000000metche 1.1 * configuration: report e-mails' subject is now automatically prepended by the hostname of the monitored system; you may have to update your _MAIL_SUBJECT configuration in /etc/metche.conf, if you have customized it. metche-1.2.4/README000066400000000000000000000134231312467753200136600ustar00rootroot00000000000000metche - reducing root bus factor homepage: https://0xacab.org/metche/metche/ Git repository: https://0xacab.org/metche/metche.git dev team: metche AT lists DOT riseup DOT net ,------------------------------------------------------------------------------- | Copyright (C) 2004-2006 boum.org collective - property is theft ! | Copyright (C) 2009-2011 metche developers `------------------------------------------------------------------------------- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ,------------------------------------------------------------------------------- | OVERVIEW `------------------------------------------------------------------------------- metche is a tool meant to ease collective system administration. It does periodically : - save the "system state" of . $WATCHED_DIR (default: /etc) . $CHANGELOG_FILE (default /root/Changelog) or $CHANGELOG_DIR/*/Changelog (default: /root/changelogs/*/Changelog) . Debian packages states and versions if $DO_PACKAGES is set to "yes" (default: no) to $BACKUP_DIR (default: /var/lib/metche). - send a nicely formatted email to a defined email address, listing the last changes that have been made to the system. See https://0xacab.org/metche/metche for an example. ,------------------------------------------------------------------------------- | BASIC USAGE `------------------------------------------------------------------------------- When installed and configured, metche is run by a cron job. You just have to read the report emails. Of course it's not useful at all if you don't: - set the $EMAIL_ADDRESS config variable to your sysadmins' collective mailing-list or email address; - use the Changelog files in a rigorous way. Note: It is dangerous to use metche without reading the SECURITY section of the manpage before. For further explanation of the way metche works, read the metche(8) manpage and the FAQ file. ,------------------------------------------------------------------------------- | REQUIREMENTS `------------------------------------------------------------------------------- * Debian GNU/Linux and apt-show-versions (if Debian package monitoring is enabled) * mutt or mail or sendmail * bzip2 * If you want metche to encrypt the email it sends: gnupg * If you want metche to monitor your vservers as well: util-vserver tools * If you want metche to monitor one manually written Changelog file, it must be located at $CHANGELOG_FILE. _or_ If you want metche to monitor multiple manually written Changelog files, they must be located in $CHANGELOG_DIR/*/Changelog; for example this way: /root/ changelogs/ common/Changelog apache/Changelog postfix/Changelog ,------------------------------------------------------------------------------- | INSTALLATION `------------------------------------------------------------------------------- Please see the included INSTALL file. ,------------------------------------------------------------------------------- | CONFIGURATION `------------------------------------------------------------------------------- 1. Copy metche.conf.default to /etc/metche.conf and edit it so that it suits your needs. 2. Read the next sections of this document and the metche(8) manpage. 3. Add to /etc/cron.d/metche something like: 0-59/5 * * * * root test -x /usr/local/sbin/metche && \ /usr/local/sbin/metche cron See the cron (8) manpage for further explanations on how to create a cron job. ,------------------------------------------------------------------------------- | VSERVERS SUPPORT `------------------------------------------------------------------------------- Just add one (or more) VServer name to the VSNAMES configuration variable, and metche will monitor it in addition to the host system: - the WATCHED_DIR, CHANGELOG_DIR and CHANGELOG_FILE paths are also used, relatively to your VServer's root directory; - the "system state" backups will be saved in sub-directory in BACKUP_DIR's, called the same as the VServer; - EMAIL_ADDRESS is not used for the VServers: the report messages will be sent to the root email address of the VServer; if you're using ENCRYPT_EMAIL to encrypt the report messages, make sure the relevant public key are in the host system root's keyring, trusted enough to be used blindly by metche; - all other configuration variables are used as it. Most of metche commands (namely: list, report and stabilize) support a '-h ' option: - if -h is specified, metche only operates on the VServer provided as an argument; - else, metche only operates on the host system. Troubleshooting: in case you have a not-purely-Debianish VServer setup, you may have to customize some of the VServers-related configuration variables. See the comments in metche.conf for more details. ,------------------------------------------------------------------------------- | SECURITY WARNING `------------------------------------------------------------------------------- Read the SECURITY section of metche(8). Really. metche-1.2.4/metche000077500000000000000000000650471312467753200142040ustar00rootroot00000000000000#! /bin/bash # -*- mode: sh; sh-basic-offset: 4; indent-tabs-mode: nil; -*- # # metche: reducing root bus factor # Copyright (C) 2004-2006 boum.org collective - property is theft ! # Copyright (C) 2009-2011 metche developers # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # set -e shopt -s nullglob ### ### Auxiliary functions ### display_usage() { ( echo "Usage:" echo " `basename $0` [-h VSERVER] list" echo " `basename $0` [-h VSERVER] report" \ "[{stable|testing|unstable}-YYYYMMDDHHMM]" echo " `basename $0` [-h VSERVER] stabilize [testing-YYYYMMDDHHMM]" echo "" echo " With -h, the VServer VSERVER is operated on instead of the host system." echo "" echo "Non-interactive usage:" echo " `basename $0` cron" echo "" ) >&2 } fatal() { echo -e "Fatal: $@" >&2 exit 2 } warning() { echo -e "Warning: $@" >&2 } debug() { [ "$DEBUG" != yes ] || echo -e "Debug: $@" >&2 } executable_not_found() { local executable="$1" local software="$2" local dependant_option="$3" local solution_option="$4" if [ -z "$solution_option" ]; then fatal "$executable not found on `current_system`." \ "Please install $software or turn $dependant_option off." else fatal "$executable not found on `current_system`." \ "Please install $software, customize $solution_option" \ "or turn $dependant_option off." fi } add_header() { local subject="$1" echo "Subject: $subject" echo "To: $EMAIL_ADDRESS" echo cat } _mail() { local subject="$1" if which mutt > /dev/null ; then LC_ALL="$LOCALE" mutt -F/dev/null -e 'set record="/dev/null"' -s "$subject" "$EMAIL_ADDRESS" elif which mail > /dev/null ; then LC_ALL="$LOCALE" mail -s "$subject" "$EMAIL_ADDRESS" elif [ -x /usr/sbin/sendmail ]; then LC_ALL="$LOCALE" add_header "$subject"|/usr/sbin/sendmail "$EMAIL_ADDRESS" fi } email() { debug "* email $@ to $EMAIL_ADDRESS" local subject="`current_system` - $_MAIL_SUBJECT : $1" if [ $ENCRYPT_EMAIL = "yes" ]; then LC_ALL="$LOCALE" gpg --batch --armor --encrypt \ --recipient "$EMAIL_ADDRESS" | LC_ALL="$LOCALE" _mail "$subject" else LC_ALL="$LOCALE" _mail "$subject" fi } current_system() { $VSERVER_EXEC_PREFIX hostname -f } ### ### Configuration ### DEBUG="yes" WATCHED_DIR="/etc" BACKUP_DIR="/var/lib/metche" # if set, activate single changelog mode #CHANGELOG_FILE="/root/Changelog" # if set, activate multiple changelogs mode #CHANGELOG_DIR="/root/changelogs" DO_PACKAGES="no" DO_DETAILS="no" TESTING_TIME="60" STABLE_TIME="3" EMAIL_ADDRESS="root@`hostname -f`" ENCRYPT_EMAIL="no" SEND_STABLE_REPORTS="yes" EXCLUDES=".git _darcs .svn .bzr CVS .hg _FOSSIL_ \ *.swp #* *~ *.gpg *.key ifstate adjtime ld.so.cache shadow* \ .cache .gnupg blkid.tab* aumixrc net.enable mtab backup.d \ vdirbase run.rev vdir run.rev \ prng_exch smtp_scache.pag smtpd_scache.pag \ smtp_scache.dir smtpd_scache.dir local.sh \ ssh_host_dsa_key* ssh_host_rsa_key*" LOCALE="C" VSNAMES="" VSERVERINFO=/usr/sbin/vserver-info VSERVER=/usr/sbin/vserver _MAIL_SUBJECT="changes report" _NO_DEBIAN_PACKAGES_CHANGE="No change in Debian packages state." _NO_CHANGE="No change." MAIN_HEADER=" c h a n g e s r e p o r t --------------------------- " CHANGELOGS_HEADER=" Changelogs ========== " FILES_HEADER=" Changed files ============= " DEBIAN_PACKAGES_HEADER=" Changes in Debian packages ========================== " FILES_DETAILS_HEADER=" Details for changed files ========================= " if [ "$1" = "-h" ]; then VSNAME="$2" CMD="$3" MILESTONE="$4" else CMD="$1" MILESTONE="$2" fi if [ -f /etc/metche.conf ]; then . /etc/metche.conf else display_usage fatal "Config file not found." fi PATH="/bin:/usr/bin" unset LC_ALL unset LC_COLLATE unset LC_CTYPE unset LANGUAGE unset LANG umask 077 # Manage deprecated configuration files and options test ! -d /etc/metche || fatal "An old configuration directory (/etc/metche/)" \ "was found, please upgrade your configuration." test -z "$TAR_OPTS" || fatal "TAR_OPTS is deprecated, use EXCLUDES instead." # Backup various configuration values: these non-underscored variable # names will be re-initialized in context_config() and re-used everywhere. _WATCHED_DIR="$WATCHED_DIR" _BACKUP_DIR="$BACKUP_DIR" _CHANGELOG_DIR="$CHANGELOG_DIR" _CHANGELOG_FILE="$CHANGELOG_FILE" _DO_PACKAGES="$DO_PACKAGES" _EMAIL_ADDRESS="$EMAIL_ADDRESS" if [ -n "$VSNAMES" ]; then # check VSERVERINFO and VSERVER availability test -x "$VSERVERINFO" || \ executable_not_found "vserver-info" "util-vserver" "VSNAMES" "VSERVERINFO" test -x "$VSERVER" || \ executable_not_found "vserver" "util-vserver" "VSNAMES" "VSERVER" # check VROOTDIR availability test -n "$VROOTDIR" || \ VROOTDIR="`$VSERVERINFO info SYSINFO \ | grep '^ *vserver-Rootdir' | awk '{print $2}'`" test -n "$VROOTDIR" || \ fatal "VSNAMES is not empty, but VROOTDIR could not be guessed." \ "Please set VROOTDIR in /etc/metche.conf." test -d "$VROOTDIR" || \ fatal "VSNAMES is not empty, but VROOTDIR ($VROOTDIR) does not exist." \ "Please set VROOTDIR in /etc/metche.conf." # expand VSNAMES if it is set to "all" if [ "$VSNAMES" = all ]; then VSNAMES=`ls $VROOTDIR | grep -E -v "lost\+found|ARCHIVES" | tr "\n" " "` if [ -z "$VSNAMES" ]; then warning "VSNAMES is set to \"all\", but no VServer could be found" \ "in VROOTDIR ($VROOTDIR)." fi fi fi if [ "$ENCRYPT_EMAIL" = "yes" ]; then which gpg > /dev/null || executable_not_found "gpg" "GnuPG" "ENCRYPT_EMAIL" fi DATE=`date "+%Y%m%d%H%M"` # How to use $TAR_OPTS: # - $TAR_OPTS should be used unquoted # - 'set -o noglob' has to be run before any $TAR_OPTS use # - 'set +o noglob' has to be run after any $TAR_OPTS use TAR_OPTS="" set -o noglob for pattern in $EXCLUDES; do TAR_OPTS="$TAR_OPTS --exclude=$pattern" done set +o noglob # How to use $_FIND_OPTS: # - 'set -o noglob' has to be run before any $_FIND_OPTS use # - 'set +o noglob' has to be run after any $_FIND_OPTS use _FIND_OPTS="" set -o noglob # DO NOT fix me: the final -or at the end of $_FIND_OPTS is really needed for pattern in $EXCLUDES; do _FIND_OPTS="$_FIND_OPTS -path */$pattern -prune -or" done set +o noglob ### ### A few functions to do the real work ### # Check and mangle the context-dependant configuration variables, # i.e. the parameters specific to the host system or to a given VServer. # If $1 is empty, operate on the host system. # Else, operate on a VServer and return with exit-code: # - 2 if $1 is not an existing VServer # - 3 if $1 is not a VServer listed in VSNAMES # - 4 if $1 is not a running VServer # Anyway, return with exit-code: # - 5 if the GnuPG public key can not be found context_config() { local vsname="$1" local res debug "-------- Operating on" \ "`if [ -z $vsname ]; then echo 'the host system'; else echo VServer $vsname; fi`" debug "* context_config" # # Variables & VServer # if [ -z "$vsname" ]; then WATCHED_DIR="$_WATCHED_DIR" BACKUP_DIR="$_BACKUP_DIR" VSERVER_EXEC_PREFIX="" EMAIL_ADDRESS="$_EMAIL_ADDRESS" else WATCHED_DIR="$VROOTDIR/$vsname/$_WATCHED_DIR" BACKUP_DIR="$_BACKUP_DIR/$vsname" VSERVER_EXEC_PREFIX="$VSERVER $vsname exec" EMAIL_ADDRESS="root@`current_system`" # does the current VServer exist ? if [ ! -d "$VROOTDIR/$vsname" ]; then warning " VServer $vsname does not exist (error 2)." return 2 fi # is the current VServer listed in VSNAMES ? local found="no"; for i in $VSNAMES; do if [ "$vsname" = "$i" ]; then found=yes break fi done if [ $found = no ]; then warning " VServer $vsname is not listed in VSNAMES (error 3)." return 3 fi # is the current VServer running ? res="" $VSERVERINFO -q "$vsname" RUNNING || res=failed if [ "$res" = failed ]; then warning " VServer $vsname is not running (error 4)." return 4 fi fi # E-mail encryption if [ $ENCRYPT_EMAIL = "yes" ]; then echo | gpg --batch --encrypt --recipient $EMAIL_ADDRESS >/dev/null 2>&1 res=$? if [ $res -ne 0 ]; then warning " GnuPG public key for $EMAIL_ADDRESS not found." return 5 fi fi # # Files and directories # # Check the existence of WATCHED_DIR test -d "$WATCHED_DIR" || \ fatal "$WATCHED_DIR directory (built from WATCHED_DIR) does not exist." # Initialize $FIND_OPTS -- how to use it: # - 'set -o noglob' has to be run before any $FIND_OPTS use # - 'set +o noglob' has to be run after any $FIND_OPTS use # - $FIND_OPTS should appear unquoted between: # . the (optional) target files and directories # . the (compulsory) action, such as -print or -exec set -o noglob FIND_OPTS="-path $WATCHED_DIR -or $_FIND_OPTS" set +o noglob # Initialize WATCHED_PARENT WATCHED_PARENT=`dirname $WATCHED_DIR` if [ "$WATCHED_PARENT" != '/' ]; then WATCHED_PARENT="$WATCHED_PARENT/" fi # Check the existence of the resulting BACKUP_DIR, creating it if needed. if [ ! -d "$BACKUP_DIR" ]; then debug " Creating $BACKUP_DIR directory for `current_system`." if mkdir -p "$BACKUP_DIR"; then debug " Successfully created $BACKUP_DIR directory." else fatal " Failed to create $BACKUP_DIR directory." fi fi # # Modules enabling/disabling # # DO_CHANGELOGS DO_CHANGELOGS="no" if [ -n "$_CHANGELOG_DIR" ]; then if [ -z "$vsname" ]; then CHANGELOG_DIR="$_CHANGELOG_DIR" else CHANGELOG_DIR="$VROOTDIR/$vsname$_CHANGELOG_DIR" fi if [ -d "$CHANGELOG_DIR" ]; then DO_CHANGELOGS="dir" else warning " The directory $CHANGELOG_DIR (built from CHANGELOG_DIR)" \ " does not exist. Changelogs file monitoring thereferore" \ " cannot be performed this time for `current_system`." fi elif [ -n "$CHANGELOG_FILE" ]; then if [ -z "$vsname" ]; then CHANGELOG_FILE="$_CHANGELOG_FILE" else CHANGELOG_FILE="$VROOTDIR/$vsname$_CHANGELOG_FILE" fi if [ -f "$CHANGELOG_FILE" ]; then DO_CHANGELOGS="file" else warning " The file $CHANGELOG_FILE (built from CHANGELOG_FILE)" warning " does not exist. Changelog file monitoring thereferore" warning " cannot be performed this time for `current_system`." fi fi # DO_PACKAGES DO_PACKAGES="$_DO_PACKAGES" if [ "$DO_PACKAGES" = "yes" ]; then $VSERVER_EXEC_PREFIX which apt-show-versions > /dev/null res=$? if [ $res -ne 0 ]; then warning " apt-show-versions not found on `current_system`." warning " Please install it or turn DO_PACKAGES off." warning " DO_PACKAGES therefore cannot be performed this time" warning " for `current_system`." DO_PACKAGES=no fi fi # # Final steps to get a coherent initial status # # Make sure we've got at least one testing and one stable milestone_exists testing-latest || save_state "testing" milestone_exists stable-latest || stabilize_state "testing-latest" } # Returns 0 if, and only if, specified milestone exists. milestone_exists() { local milestone="$1" if [ -f "${BACKUP_DIR}/${milestone}.tar.bz2" -o \ -L "${BACKUP_DIR}/${milestone}.tar.bz2" ]; then return 0 else return 1 fi } # Echoes the given milestone's version (i.e. "stable", "testing", "unstable") # if it has a valid version, else "none". # The given milestone can be inexistant. milestone_version() { local milestone="$1" local version="`echo $milestone | sed 's/-.*$//'`" case $version in stable|testing|unstable) echo $version;; *) echo "none";; esac } # Echoes given milestone's date. # Symlinks (e.g.: *-latest) are dereferenced if needed. # The given milestone can be inexistant. milestone_date() { local milestone="$1" if [ -L "${BACKUP_DIR}/${milestone}.tar.bz2" ]; then milestone="`readlink ${BACKUP_DIR}/${milestone}.tar.bz2`" fi echo `basename $milestone` | sed 's/.*-//' | sed 's/\..*$//' } # Returns 0 if, and only if, the given milestone ($1) is the latest one # of its type. # The given milestone can be inexistant. is_latest() { local file milestone ref_milestone ref_date ref_version ref_milestone="$1" ref_date="`milestone_date $ref_milestone`" ref_version="`milestone_version $ref_milestone`" for file in "${BACKUP_DIR}/${ref_version}-"*.tar.bz2; do milestone=`basename $file | sed 's/\.tar\.bz2$//'` if [ "`milestone_date $milestone`" -gt "$ref_date" ]; then return 1 fi done return 0 } # This will save an archive of the watched directory with the given prefix save_files() { debug " - save_files $@" set -o noglob tar jcf "$BACKUP_DIR/$1-$DATE".tar.bz2 \ -C "$WATCHED_PARENT" $TAR_OPTS `basename "$WATCHED_DIR"` set +o noglob ln -sf "$1-$DATE".tar.bz2 "$BACKUP_DIR/$1"-latest.tar.bz2 } # This will save packages list with the given prefix save_packages() { debug " - save_packages $@" $VSERVER_EXEC_PREFIX apt-show-versions -i $VSERVER_EXEC_PREFIX apt-show-versions | sort > "$BACKUP_DIR/$1-$DATE".packages ln -sf "$1-$DATE".packages "$BACKUP_DIR/$1"-latest.packages } # This will save Changelogs with the given prefix save_changelogs() { debug " - save_changelogs $@" local changelog domain file if [ "$DO_CHANGELOGS" = "dir" ]; then for file in "$CHANGELOG_DIR"/*/Changelog; do changelog="${file##$CHANGELOG_DIR/}" domain="${changelog%%/Changelog}" cat "$file" > "$BACKUP_DIR/$1-$DATE.$domain.Changelog" ln -sf "$1-$DATE.$domain.Changelog" \ "$BACKUP_DIR/$1-latest.$domain.Changelog" done elif [ "$DO_CHANGELOGS" = "file" ]; then cat "$CHANGELOG_FILE" > "$BACKUP_DIR/$1-$DATE.Changelog" ln -sf "$1-$DATE.Changelog" "$BACKUP_DIR/$1-latest.Changelog" fi } # Save whatever reflect the current state with the given prefix save_state() { debug "* save_state $@" save_files "$1" [ $DO_PACKAGES = "no" ] || save_packages "$1" [ $DO_CHANGELOGS = "no" ] || save_changelogs "$1" } # Report changes against given version to standard output report_changes() { debug "* report_changes $@" local tmp tmpdir changelog domain diff tar_diff diff_diff local files old new tmp_packages file # File to store results tmp=`mktemp -q` # We need to diff against given version, so extract it tmpdir=`mktemp -d -q` tar jxf "$BACKUP_DIR/$1".tar.bz2 -C "$tmpdir" echo "$MAIN_HEADER" >> "$tmp" if [ $DO_CHANGELOGS = "dir" ]; then echo "$CHANGELOGS_HEADER" >> "$tmp" for file in "$CHANGELOG_DIR"/*/Changelog; do changelog="${file##$CHANGELOG_DIR/}" domain="${changelog%%/Changelog}" diff=`LC_ALL=$LOCALE \ diff -wEbBN "$BACKUP_DIR/$1.$domain.Changelog" \ "$file"` || # diff returns false when files differ (echo "$domain:" ; echo "$diff" | grep -v '^[0-9-]\|^\\') >> "$tmp" done fi if [ $DO_CHANGELOGS = "file" ]; then echo "$CHANGELOGS_HEADER" >> "$tmp" diff=`LC_ALL=$LOCALE \ diff -wEbBN "$BACKUP_DIR/$1.Changelog" "$CHANGELOG_FILE"` || # diff returns false when files differ (echo "$diff" | grep -v '^[0-9-]\|^\\') >> "$tmp" fi echo "$FILES_HEADER" >> "$tmp" # Find differences with tar set -o noglob tar_diff=$(tar jdf "$BACKUP_DIR/$1".tar.bz2 \ -C "$WATCHED_PARENT" $TAR_OPTS 2>&1 | # transform: # etc/issue: Gid differs -> etc/issue # tar: etc/irssi.conf: ... -> etc/irssi.conf sed -e 's/\(tar: \)\?\([^:]*\):.*/\2/') # Get new files diff_diff=$(diff -qr $TAR_OPTS "$tmpdir"/`basename "$WATCHED_DIR"` \ "$WATCHED_DIR" 2>/dev/null | # Only in test/etc: issue -> test/etc/issue sed -n -e "s,^Only in $WATCHED_PARENT\([^:]*\): \(.*\),\1/\2,p") files="`echo "$tar_diff$diff_diff" | sort -u`" set +o noglob if [ -z "$files" ]; then echo "$_NO_CHANGE" >> "$tmp" else for file in $files; do old="$tmpdir"/"$file" new="$WATCHED_PARENT$file" if [ -e "$old" -a -e "$new" ]; then echo -n '< ' ls -ld "$old" | sed -e "s;$tmpdir/;;" echo -n '> ' ls -ld "$new" | sed -e "s;$WATCHED_PARENT;;" elif [ -e "$old" ]; then echo -n '- ' ls -ld "$old" | sed -e "s;$tmpdir/;;" elif [ -e "$new" ]; then echo -n '+ ' ls -ld "$new" | sed -e "s;$WATCHED_PARENT;;" fi done >> "$tmp" fi if [ "$DO_PACKAGES" = "yes" ]; then echo "$DEBIAN_PACKAGES_HEADER" >> "$tmp" tmp_packages=`mktemp -q` $VSERVER_EXEC_PREFIX apt-show-versions -i $VSERVER_EXEC_PREFIX apt-show-versions | sort > "$tmp_packages" if diff -wEbBN "$BACKUP_DIR/$1".packages "$tmp_packages"; then echo "$_NO_DEBIAN_PACKAGES_CHANGE" fi | grep -v '^[0-9-]' >> "$tmp" fi if [ "$DO_DETAILS" = "yes" ]; then echo "$FILES_DETAILS_HEADER" >> "$tmp" # Just diff it! set -o noglob if (LC_ALL=$LOCALE diff -urBN $TAR_OPTS \ --minimal "$tmpdir"/`basename "$WATCHED_DIR"` \ "$WATCHED_DIR" 2>/dev/null); then echo "$_NO_CHANGE" fi | grep -v '^--- \|diff ' | sed -e "s;^+++ $WATCHED_PARENT\([^ ]*\) .*;+++ \1;" \ >> "$tmp" set +o noglob fi # Put on standard output cat "$tmp" # Clean temporaries rm -rf "$tmp" "$tmpdir" } # Turns into stable the given testing. # NB: argument validity is supposed to have been already checked. stabilize_state() { debug "* stabilize_state $@" local testing stable file dst testing="$1" # follow symlink if needed if [ -L "${BACKUP_DIR}/$testing".tar.bz2 ]; then testing="`readlink ${BACKUP_DIR}/${testing}.tar.bz2`" testing="`basename $testing | sed 's/\..*//'`" fi stable="`echo $testing | sed 's/^testing/stable/'`" for file in "${BACKUP_DIR}/${testing}"*; do dst="`echo $file | sed 's/\/testing-/\/stable-/'`" cp "$file" "$dst" # create/change stable-latest* links if, and only if, # it's really the latest if is_latest $stable; then ln -sf "`basename $dst`" "${BACKUP_DIR}/`basename $dst | sed 's/-[0-9]*\./-latest\./'`" fi done if [ "${SEND_STABLE_REPORTS}" = yes ]; then echo "metche saved a new stable state: $stable." | email "$stable" fi } # Print watched directory and files separated by spaces # (suitable for find) # Note: this function needs pathname expansion, but is called from places where # it is disabled; that's why we need to save the pathname expansion status # in the beginning and reset it to end with. print_watched_files() { local files local reset_noglob_status_cmd files="$WATCHED_DIR" reset_noglob_status_cmd="`set +o | grep 'set .o noglob'`" set +o noglob if [ "$DO_CHANGELOGS" = "dir" ]; then files="$files `echo "$CHANGELOG_DIR"/*/Changelog`" elif [ "$DO_CHANGELOGS" = "file" ]; then files="$files $CHANGELOG_FILE" fi $reset_noglob_status_cmd echo "$files" } # Return true if watched files has not changed since $1 minutes no_change_since() { local time time="$1" set -o noglob if [ -z "$(find $(print_watched_files) $FIND_OPTS -cmin "-$time" -print | head -1)" ]; then set +o noglob return 0 else set +o noglob return 1 fi } # Return true if watched files has changed since file $1 last modification changed_from() { local ref_file ref_file="$1" set -o noglob if [ "$(find $(print_watched_files) $FIND_OPTS -newer "$ref_file" -print | head -1)" ]; then set +o noglob return 0 else set +o noglob return 1 fi } ### ### Main ### case "$CMD" in report) context_config "$VSNAME" || fatal "Aborting (error $?)." DO_DETAILS="yes" if [ -z "$MILESTONE" ]; then report_changes "testing-latest" elif milestone_exists "$MILESTONE"; then report_changes "$MILESTONE" else display_usage fatal "The specified state does not exist." fi ;; list) context_config "$VSNAME" || fatal "Aborting (error $?)." for file in "$BACKUP_DIR"/*.tar.bz2; do echo `basename ${file%%.tar.bz2}` done ;; cron) STABLE_TIME_MIN=`expr 24 '*' 60 '*' "$STABLE_TIME"` if [ -n "$VSNAME" ]; then display_usage fatal "-h option not available for 'metche cron'" fi for i in "" $VSNAMES; do res=0 context_config "$i" || res=$? if [ $res -ne 0 ]; then warning "-------- Ignoring" \ "`if [ -z $i ]; then \ echo 'the host system'; \ else \ echo VServer $i; fi` (error $res)" continue fi ### Algorithm # # if (no change happened for TESTING_TIME) then # if (something has changed since the last testing) then # send a report against last testing # save a new testing state # delete all saved unstable states # elif (no change happened for STABLE_TIME) then # if (something has changed since the last stable) then # save a new stable state and notify EMAIL_ADDRESS # delete all saved testing states older than STABLE_TIME # fi # fi # elif (last unstable exists) then # if (something has changed since the last unstable) then # save a new unstable state # fi # else # save a new unstable state # fi debug "* main algorithm" if no_change_since "$TESTING_TIME"; then debug " no change since TESTING_TIME" if changed_from "$BACKUP_DIR"/testing-latest.tar.bz2; then debug " changed from testing-latest" report_changes "testing-latest" | email "testing-$DATE" save_state "testing" debug " removing all saved unstable states." find "$BACKUP_DIR" -name 'unstable-*' -exec rm "{}" \; elif no_change_since "$STABLE_TIME_MIN"; then if changed_from "$BACKUP_DIR"/stable-latest.tar.bz2; then save_state "stable" if [ "${SEND_STABLE_REPORTS}" = yes ]; then echo "metche saved a new stable state: stable-${DATE}." | email "stable-$DATE" fi debug " removing all saved testing states older" \ "than STABLE_TIME ($STABLE_TIME)." find "$BACKUP_DIR" -name 'testing-*' \ -ctime +"$STABLE_TIME" -exec rm "{}" \; fi fi elif milestone_exists unstable-latest; then if changed_from "$BACKUP_DIR"/unstable-latest.tar.bz2; then debug " changed from unstable-latest" save_state "unstable" else debug " not changed from unstable-latest" fi else save_state "unstable" fi done ;; stabilize) context_config "$VSNAME" || fatal "Aborting (error $?)." if [ -z "$MILESTONE" ]; then stabilize_state "testing-latest" elif [ "`milestone_version $MILESTONE`" = "testing" -a \ milestone_exists $MILESTONE ]; then stabilize_state "$MILESTONE" else display_usage fatal "The specified state is not an existing testing state." fi ;; test) for i in "" $VSNAMES; do res=0 context_config "$i" || res=$? if [ $res -ne 0 ]; then warning "-------- Ignoring" \ "`if [ -z $i ]; then \ echo 'the host system'; \ else \ echo VServer $i; fi` (error $res)" continue fi milestone_version "stable-200507040202" milestone_version "testing-latest" milestone_date "testing-latest" #report_changes "testing-latest" | email "testing-$DATE" done ;; *) display_usage exit 1 ;; esac # vim: et sw=4 metche-1.2.4/metche.8.markdown000066400000000000000000000112711312467753200161560ustar00rootroot00000000000000% METCHE(8) metche user manual % metche and this manual page were written by the boum.org collective, and are now maintained by the metche developers collective % June 5, 2011 NAME ==== metche - reducing root bus factor SYNOPSIS ======== metche [-h VSERVER] report (stable|testing|unstable)-YYYYMMDDHHMM metche [-h VSERVER] list metche [-h VSERVER] stabilize testing-YYYYMMDDHHMM DESCRIPTION =========== metche is a tool meant to ease collective system administration by monitoring changes in the system configuration. metche basic usage is to monitor changes in a directory, usually `/etc`; optionally, metche can also monitor: * one or more user maintained changelog files, * the state of Debian packages and versions. metche should be installed with a cronjob that regularly runs to automatically save the system state as needed. These states are saved in a way similar to the Debian development model: * _unstable_ states are saved as soon as a change is detected. They are kept until a new _testing_ state appears. * _testing_ states is created from the last _unstable_ state that has not been changed after a short amount of time (by default, one hour). Old _unstable_ states are deleted afterwards. * _stable_ states are created from the last _testing_ state, either manually, or after a long amount of time (by default, 3 days). Old _testing_ states are deleted afterwards. When a new _testing_ state is saved, an email is sent to a configurable address, giving an overwiew of the differences with the previous _testing_. A notification is also sent when a new _stable_ state is saved. metche's configuration is read from `/etc/metche.conf`. Various settings like changelog monitoring or time between system state switches are described there. OPTIONS ======= If `-h VSERVER` is specified, the VServer _VSERVER_ is operated on instead of the host system. This, along with the `VSNAMES` option, allows one to monitor several VServers running on the system. One of the following commands must be specified on the command line: report : When run with the _report_ command, metche displays a report against the specified saved state, or if unspecified, against the latest testing state. This is useful when you have broken your system and want to know which changes have been made since a given, known working, system state. list : When run with the _list_ command, metche displays a list of all the saved states. stabilize : When run with the _stabilize_ command, metche turns a "testing state" into a "stable state". By default, it will use the last "testing state", but this can be overridden by giving a specific state as argument. cron : This command should not be called manually, but used from a cronjob. When called, it can perform various operations like: saving "unstable", "testing" or "stable" states as needed and sending reports and notification if configured to do so. This command does not support the `-h` option. FILES ===== `/etc/metche.conf` contains metche configuration. When configured to monitor one changelog, `CHANGELOG_FILE` (default: `/root/Changelog`). When configured to monitor multiple changelogs, `CHANGELOG_DIR/*/Changelog` (default: `/root/changelogs`). System states are saved in `BACKUP_DIR` (default: `/var/lib/metche`). SECURITY ======== metche is able to use GnuPG to encrypt the email it sends, but does not by default; just enable the `ENCRYPT_EMAIL` configuration option, and make sure `EMAIL_ADDRESS`' public key is in root's keyring, trusted enough to be used blindly by metche. If `EMAIL_ADDRESS` is an email alias or mailing-list's address, you probably want to use the `group` option in `/root/.gnupg/gpg.conf` so that metche reports are encrypted for every person subscribed to this alias or mailing-list; for more information, see `gpg(1)`. When `DO_DETAILS` is enabled and `ENCRYPT_EMAIL` is disabled, metche sends in _clear text email_ the changes made to the watched directory... either make sure that the `EXCLUDES` configuration variable prevents it to send sensitive information, or triple check that secure connections will be used end-to-end on the email path. If unsure, set `EMAIL_ADDRESS` configuration variable to a local mailbox. Please note that `EMAIL_ADDRESS` is not used for VServers: a VServer's report messages are sent to its root email address. metche stores, in `BACKUP_DIR` (default: `/var/lib/metche`), various backups of `WATCHED_DIR`. Make sure that this backup place is at least as secured as the source. BUGS ==== See [metche's ticket system] for known bugs, missing features, and the development road-map. [metche's ticket system]: https://0xacab.org/metche/metche/issues metche-1.2.4/metche.conf.default000066400000000000000000000060631312467753200165410ustar00rootroot00000000000000####################################################################### # # metche configuration # # Directory watched by metche WATCHED_DIR="/etc" # Directory containing backups BACKUP_DIR="/var/lib/metche" # Activate single changelog file monitoring CHANGELOG_FILE="/root/Changelog" # Activate multiple changelogs file monitoring. # Each "Changelog" should be in a sub-directory of CHANGELOG_DIR. # (Override CHANGELOG_FILE if both are set) #CHANGELOG_DIR="/root/changelogs" # Debian packages monitoring (need apt-show-versions) DO_PACKAGES="no" # Show diff details for modified files # WARNING! This can send sensitive data by e-mail if not used with encryption. DO_DETAILS="no" # Minutes until unstable goes to testing TESTING_TIME="60" # Days until testing goes to stable STABLE_TIME="3" # Address receiving testing changes report EMAIL_ADDRESS="root@localhost" # Encrypt emails with GnuPG ? (uncomment next line to do so) #ENCRYPT_EMAIL="yes" # Email $EMAIL_ADDRESS after saving a stable state SEND_STABLE_REPORTS="yes" # Filename patterns to ignore (space-separated list) # GNU tar --exclude pattern matching rules are used: # - If a pattern matches a directory, all the files beneath it are # recursively excluded. # - Periods (`.') or forward slashes (`/') are not considered special for # wildcard matches. # # Known cases where excludes are needed: # - "resolv.conf" when using resolvconf, # - "printcap" when cups browsing feature are used. # # Example (default value): #EXCLUDES=".git _darcs .svn .bzr CVS .hg _FOSSIL_ \ # *.swp #* *~ *.gpg *.key ifstate adjtime ld.so.cache shadow* \ # .cache .gnupg blkid.tab* aumixrc net.enable mtab backup.d \ # vdirbase run.rev vdir run.rev \ # prng_exch smtp_scache.pag smtpd_scache.pag \ # smtp_scache.dir smtpd_scache.dir local.sh \ # ssh_host_dsa_key* ssh_host_rsa_key*" # Locale (will be used to feed LC_ALL) # Warning: values different from "C" are untested. LOCALE="C" # Set this to yes to get more debugging output. DEBUG="no" ####################################################################### # # Linux VServers configuration # # VServers to monitor (space-separated list) # The host system is monitored, whatever VSERVERS is set to. # Set VSNAMES to "all" in order to monitor all VServers. #VSNAMES="" #VSNAMES="name1 name2" #VSNAMES="all" # vserver-info command location (default: /usr/sbin/vserver-info) #VSERVERINFO=/usr/sbin/vserver-info # vserver command location (default: /usr/sbin/vserver) #VSERVER=/usr/sbin/vserver # Directory where the VServers live; example: a VServer called "twiki" # will have its root directory in $VROOTDIR/twiki # (default: /var/lib/vservers) #VROOTDIR=/var/lib/vservers ####################################################################### # # Localizable strings # # Add your custom headers below #_MAIL_SUBJECT="changes report" #_NO_DEBIAN_PACKAGES_CHANGE="No change in Debian packages state." #_NO_CHANGE="No change." #MAIN_HEADER="" #CHANGELOGS_HEADER="" #FILES_HEADER="" #DEBIAN_PACKAGES_HEADER="" #FILES_DETAILS_HEADER=""