I've been giving Bug 459 (No unistall script) some thought. And I've come up
with what might well be a solution. I'd be interested to hear thoughts on the
matter.
*
[1] I've taken Galen's suggestion and added support for multiple machine
architectures.
Ostensibly this is to support unixes and variants who do not use /usr/sbin to
store userdel & groupdel commands.
[2] I've removed comments about the install logfile holding misleading
information. I believe those comments were probably mistaken and am
investigating the matter further.
** help wanted:
I'd like suggestions of Perl Interpreter Machine Type Operating System
Classifications for any machines which do not use the /usr/sbin directory for
the commands userdel and groupdel
with the exception of FreeBSD (or BSDs in general) if they do not have a
groupdel command of some kind. (Not a procedure for editing the group file, and
so forth. It must be one single command.) (**Please do not send instructions
for procedures for editing users and groups.)
Patrick Mackeown
#!/usr/bin/perl -w # please develop with -w
#
# chances are you'll need to install CPAN IO::Tee
# perl -MCPAN -e'install "IO::Tee"'
#
# written @ Mon Jul 06 13:40:53 EDT 2009 patc...@koha.org
#
use strict; # please develop with the strict pragma
use Config;
use IO::Tee;
use diagnostics;
use DBI;
use File::Copy;
use File::Path;
###################################################################
# Global Assignments
# (You may edit these values)
###################################################################
my $LOGDIR="/var/log/koha";
my $ETCDIR="/etc/koha";
my $DROPMODE="";
my $DELCOMPLETE="";
my $MODE="SAFE";
my $KOHAROOT="";
my $CONFIGFILE="";
my $TEE_DUAL_OUTPUT;
my @kohausers =qw(koha kohaadmin kohauser);
my @kohagroups =qw(koha kohaadmin kohauser);
###################################################################
# Support Multiple Machine Architectures
###################################################################
my $deluser;
my $delgroup;
for ($Config{myarchname}) {
if (/i686-linux/) {
$deluser= "/usr/sbin/userdel";
$delgroup= "/usr/sbin/groupdel";
}elsif (/i86pc-solaris/){
$deluser= "/usr/sbin/userdel";
$delgroup= "/usr/sbin/groupdel";
}elsif (/sun4-solaris/){
$deluser= "/usr/sbin/userdel";
$delgroup= "/usr/sbin/groupdel";
}else {
$deluser= "/usr/sbin/userdel";
$delgroup= "/usr/sbin/groupdel"; }
}
###################################################################
# Program Main
# (Do not edit)
###################################################################
#[1] Open an uninstall logfile
& open_logfile;
#[2] Ask for deletion info. But, only do this as an input flag
# or if you cannot locate any del info
if ($ARGV[0]){
if ($ARGV[0] =~ /-user/){
& user_input;
}else{
if ($ARGV[0] =~ /-h\b|-help\b/i){
& printhelp;
exit 0;
}else{
if ($ARGV[0] =~ /-dropdb\b/i){
& drop_the_koha_db;
exit 0;
}
}
}
}else{
& printhelpshort;
}
# Search for ENV variables
& locate_env_variables;
###################################################################
# The Unix Help Documentation
###################################################################
sub printhelp{
print $TEE_DUAL_OUTPUT <<DOCUHELP;
ENV VARS
========
When not run with user input [-user] firstly the program tries
to find out what your environment variables for PERL5LIB and
KOHA_CONF are. This isn't conclusive proof that they're the
ones we're after. But it's a start. Be warned, there could be
multiple koha installations on this machine (for any number of
reasons.)
If for whatever reason you have neither of these environment
variables set, then you'll have to try to find their values.
CONFIGS
=======
Then the program tries to locate and read koha-conf.xml files.
By default the program is configured to search for /etc/koha
and /var/log/koha. These files are set within the parameters
at the top of the program and can be edited by hand.
APACHE & Other Web Servers
==========================
The program makes no attempt (in any mode) to deal with virtual
webservers in Apache (or any other type of webserver.) Although
a koha installation requires these. They'll need removing by hand.
SAFE mode
=========
By default this installer runs in SAFE mode. Therefore it
deletes nothing. This is because, theoretically, you could
install koha in your root directory, (in single install mode,)
and then ask an installer file to remove the root directory!
Or any other directory that you chose to! What it does is inspect
(and validate your koha directory) & your koha installation and
compiles a set of instructions for you to run (if you want to,)
which would result in the de-installation of koha. What [you]
choose to do then, is up to you. There is a way of editing the
script to automate the de-installation, simply for completeness'
sake. But it's not advisable to automate it.
You could try running either the installer or the uninstaller
as the user koha, But, unless you do this in a directory owned
and accessible by the user koha, then it won't work properly.
Because, (with standard koha installation,) when you run the
installer/uninstaller as the user koha. You will get "permission
denied" in most directories. Even the dev and single installations
try to log into /var/log/koha which is not a directory that the
user koha can create. (And koha will not run unless it can write
to its logfiles.) You could make directories by hand and then
assign them to root:koha or koha:koha, or somesuch. But this
would be messy and confusing.
KOHA DATABASE & UNIX USERS
===========================
The database is assumed to be mysql. The mysql database user
able to drop databases is assumed to be called root (mysqluser)
and the koha database is called koha.
There is an implied assumption here that the koha database and
the unix groups and users are either all to be left in tact or
all to be deleted. And the default assumption is that because
you want to uninstall koha, it doesn't mean that you want to
delete the db & users. (There could be multiple installations.)
But, it's to be noted that if you want to remove any of them
using standard admin commands, it's a simple procedure.
By default the program makes no attempt to drop the database or
remove koha's users and groups. You can run it with a [-dropdb]
option. And then it will question you about databases and users
before going on to perform admin commands according to your input
instructions. But it makes just as much sense to run a mysql
command to drop the database & to use standard unix admin commands
to remove users and groups, instead. However, for the sake of
completeness, the utility is provided here, regardless. The
program doesn't have any method of swiftly and silently removing
the koha database, nor will it include one. As much as possible
is done to keep the database in tact, unless removing it is
absolutely necessary. (If you do want one you can edit the script.)
DOCUHELP
}
sub printhelpshort{
print $TEE_DUAL_OUTPUT <<SHORT;
Koha Uninstall Info
Default is SAFE mode no files are deleted.
(i) long help file
uninstall_koha.pl -help
(ii) enter koha directory to uninstall
uninstall_koha.pl -user
(iii) delete database & unix users
uninstall_koha.pl -dropdb
logs to /tmp/koha_uninstall_history.log
SHORT
}
sub badinstallinfo{
print $TEE_DUAL_OUTPUT <<BADINSTALLINFO;
Because theorectically you can install koha anywhere, you need
to check that the directory that you've been told is a koha
directory actually is one! Let's face it, it could be anything! So
you define a koharoot by what it contains. And if you're not happy
that this is one you refuse flat-out to deal with it. (End of story.)
You can remove all genuine koha files in koharoot & /etc/koha &
then test for an empty dir. If files exist there's something wrong.
Now, in theory, if we fail to validate the koharoot we will set
BADINSTALLINFO to "True" and you can believe that if we never did set
BADINSTALLINFO to true then we validated all of the directories in
koharoot, (unless a bug in the script prevented us from setting the
flag.) So, you might want to take the failure to set the flag as a
confirmation that the directory $KOHAROOT is a valid koharoot
(Personally I'd still check it by hand and see if I wanted to
delete it, or not. But for automation purposes, that's what you
could do.
There are a number of places that $KOHAROOT can be generated.
(a) the logfilereading subroutine can guess it.
(b) the user can type it in.
(c) it can be hardcoded into the program
(d) Calculated from the ENV variables.
BADINSTALLINFO
}
sub warnaboutroot{
print $TEE_DUAL_OUTPUT <<WARNBADROOT;
Koha Uninstallation Warning:
The file path: $KOHAROOT
was determined to be the location of a koha installation on your
machine. But, because $KOHAROOT/$_ does not exist. $KOHAROOT will
not be treated as an authentic koha root. And it will not be
automatically deleted. You'll probably want to visit $KOHAROOT
and determine for yourself whether or not you wish to keep it or
delete it.
WARNBADROOT
}
sub okibelieve{
print $TEE_DUAL_OUTPUT <<OKIBELIEVE;
I've verified all of the koha installation subdirectories. So,
I can say to the best of my ability that I think $KOHAROOT is
a genuine koha installation.
OKIBELIEVE
}
sub printenvfound{
print $TEE_DUAL_OUTPUT <<ENVFOUND;
I've found the ENV Variables $ENV{PERL5LIB} & $ENV{KOHA_CONF}
This isn't conclusive proof that they point to a koha installation.
The environment variables might be faulty, they could be too old or
left over from another previous koha installation, or just mistaken.
But I'm going to test them to see if I can locate a koha installation.
>From the location of the koha Perl library at: $ENV{PERL5LIB}
I make an educated guess that there is a koha installation at: $KOHAROOT
At the moment $KOHAROOT is KOHAROOT
ENVFOUND
}
sub noguarantee{
print $TEE_DUAL_OUTPUT <<NOGUARANTEE;
No guarantee that either /etc/koha-conf.xml or /etc/koha/koha-conf.xml
exists. (They may both exist or not, or niether.) And, even if one, or both,
does exist, there's no guarantee that either contains what you need (or is
current.)
NOGUARANTEE
}
sub mode{
if ($MODE =~ /SAFE/){
print $TEE_DUAL_OUTPUT <<SAFE;
Program mode is: SAFE. No files will be deleted. And the koha database will
not be dropped. A logfile was created at
/tmp/koha_uninstall_history.log
SAFE
}else{
print $TEE_DUAL_OUTPUT <<RISK;
It is not advisble to run the program in any mode other than SAFE mode.
=======================================================
YOU are responsible for ensuring that it is instructed to delete
the correct files.
RISK
}
}
###################################################################
# The Basement: This is where the code is.
###################################################################
sub open_logfile{ #Preserve the old one, (if it exists.)
if ( -f "/tmp/koha_uninstall_history.log"){
copy( "/tmp/koha_uninstall_history.log",
"/tmp/koha_uninstall_history.log.$$")
or warn "Cannot preserve old koha uninstall history log.";
if ( -f "/tmp/koha_uninstall_history.log.$$"){
unlink "/tmp/koha_uninstall_history.log";
}
}
$TEE_DUAL_OUTPUT = IO::Tee->new(">> /tmp/koha_uninstall_history.log",
\*STDOUT);
}
sub is_this_authentic_koha_root{
my $BADUNINSTALLINFO="";
my $manyerrors="0";
my @KOHAFILES=qw( bin doc intranet lib man misc opac );
foreach (@KOHAFILES) {
if ($manyerrors < 3){
if ( !-d "$KOHAROOT/$_"){
++$manyerrors;
$BADUNINSTALLINFO="True";
& warnaboutroot;
}
# Bailout of uninstall. You've been given bad uninstall info.
} else {
if ($manyerrors < 3){;
if ( -f "$KOHAROOT/$_"){
print $TEE_DUAL_OUTPUT "Validating $KOHAROOT [Found]
$_\n";
}
}
}
}
if ( "$BADUNINSTALLINFO" !~ /True/){
& okibelieve;
& prep_genuine_root_del;
}
}
sub locate_env_variables{
# The first thing we need to do is test for ENV variables
if ($ENV{KOHA_CONF}){
print $TEE_DUAL_OUTPUT "\n [Found] ENV Variable $ENV{KOHA_CONF}
\n";
& try_etc_koha_conf_xml;
}
if (!$ENV{PERL5LIB}){
if (!$ENV{KOHA_CONF}){
print $TEE_DUAL_OUTPUT "\nWARNING PERL5LIB & KOHA_CONF ENV
VARS missing!\n";
& try_etc_koha_conf_xml;
& user_input;
}
}else{
if (!$ENV{KOHA_CONF}){
print $TEE_DUAL_OUTPUT "\nWARNING KOHA_CONF ENV VAR
missing!\n";
}else{
print $TEE_DUAL_OUTPUT "\n [Found] ENV Variable
$ENV{KOHA_CONF} \n";
& try_etc_koha_conf_xml;
}
# Env variables are present.
$KOHAROOT=$ENV{PERL5LIB};
if ( $ENV{PERL5LIB} =~ /lib\// ){
$KOHAROOT =~ s/lib\///;
}else{
$KOHAROOT =~ s/lib//;
}
$KOHAROOT =~ s/koha\//koha/;
& printenvfound;
& is_this_authentic_koha_root;
}
}
sub try_etc_koha_conf_xml{
if ( -f "/etc/koha-conf.xml" ){
$CONFIGFILE="/etc/koha-conf.xml";
& read_config_file;
& del_conf;
}else{
if ( -f "/etc/koha/koha-conf.xml" ){
$CONFIGFILE="/etc/koha/koha-conf.xml";
& read_config_file;
& del_conf;
}else{
if ( -f "$ENV{KOHA_CONF}" ){
$CONFIGFILE="$ENV{KOHA_CONF}";
& read_config_file;
& del_conf;
}
}
sub read_config_file{
my $etc_conf_log;
print $TEE_DUAL_OUTPUT "\n\n [Found] Config at loc
$CONFIGFILE \n";
open(CONFIG_FILE, "<$CONFIGFILE");
while (<CONFIG_FILE>){
if ($_ =~ /install_log/){
s/\<install_log\>//; # config is XML trim this
off
s/\<\/install_log\>//;
s/\s+//g;
chomp;
$etc_conf_log = $_;
if ( -f "$etc_conf_log" ){
$KOHAROOT=$etc_conf_log;
$KOHAROOT =~ s/koha-install-log//;
$KOHAROOT =~ s/misc\///;
print $TEE_DUAL_OUTPUT <<EOF2;
I have located a koha installation log file history at $etc_conf_log
However, there is no guarantee that the logfile is either current or
accurate.
From the location of the koha logfile at: $etc_conf_log
I make an educated guess that there is a koha installation at: $KOHAROOT
EOF2
& is_this_authentic_koha_root;
}
}
}
}
}
}
sub user_input{
if ($DELCOMPLETE !~ /True/){
print $TEE_DUAL_OUTPUT "Enter location of your koha installation\n";
my $kohainstallation=(<STDIN>);
chop $kohainstallation;
if ( -d $kohainstallation ){
$KOHAROOT = "$kohainstallation";
print " [Found] $KOHAROOT Do you want to delete it? Yes or
No?\n";
my $continue2=(<STDIN>);
chop $continue2;
if ($continue2 =~ /^Y\b|^yes|^y\b|^Yes/i) { # Uninstall
user-specified koharoot
& is_this_authentic_koha_root;
}
}else{
print <<EOF1;
The user-specified directory $kohainstallation does not exist.
Please locate
your koha installation and rerun the script.
EOF1
exit 0;
}
}
}
sub prep_genuine_root_del{
& mode;
if ( $MODE =~ /SAFE/){
}else{
if ( $MODE =~ /INSECURE/){
& deletelogs;
if (-d "$ETCDIR"){
rmtree($ETCDIR) or warn $!;
my @ETCKOHACONTENTS=qw( koha-httpd.conf pazpar2
README.txt zebradb );
foreach (@ETCKOHACONTENTS) {
if ( -e "$ETCDIR/$_"){
print $TEE_DUAL_OUTPUT "[DELETING]
$ETCDIR/$_\n";
rmtree("$ETCDIR/$_") or warn $!;
}
}
rmdir ("$ETCDIR/$_") || warn (" [ERROR IN DELETING]
$ETCDIR/$_ $?");
}
my @KOHAFILES=qw( bin doc intranet lib man misc
opac );
foreach (@KOHAFILES) {
if ( -d "$KOHAROOT/$_"){
rmtree("$KOHAROOT/$_") or warn $!;
print $TEE_DUAL_OUTPUT "[DELETING]
$KOHAROOT/$_\n";
if ( -d "$KOHAROOT/etc"){
print $TEE_DUAL_OUTPUT "[DELETING]
$KOHAROOT/etc\n";
rmtree("$KOHAROOT/etc") or warn $!;
}
if ( -d "$KOHAROOT/var"){
print $TEE_DUAL_OUTPUT "[DELETING]
$KOHAROOT/var\n";
rmtree("$KOHAROOT/var") or warn $!;
}
}
}
if ( -e "$KOHAROOT"){
print $TEE_DUAL_OUTPUT "[DELETING] $KOHAROOT\n";
rmdir ("$KOHAROOT") || warn (" [ERROR IN DELETING]
$KOHAROOT $?");
}
print $TEE_DUAL_OUTPUT "[DELETION COMPLETE]\n";
$DELCOMPLETE="True";
print $TEE_DUAL_OUTPUT "[DROPPING] the koha database\n";
& drop_the_koha_db;
}
}
}
sub del_conf{
if ( $MODE =~ /SAFE/){
print $TEE_DUAL_OUTPUT " Program mode is: SAFE. No files will be
deleted. \n";
}else{
if ( $MODE =~ /INSECURE/){
if ( -e $CONFIGFILE){
print $TEE_DUAL_OUTPUT "\n\n [DELETING]
Config at loc $CONFIGFILE \n";
unlink $CONFIGFILE;
}
}
}
}
sub drop_the_koha_db{
# You really want to make sure that you really want to do this!
print "Do you want to drop the koha database? Yes or No?\n";
my $dropit=(<STDIN>);
chop $dropit;
if ($dropit =~ /^Y\b|^yes|^y\b|^Yes/i) { # You have permission to drop
the database
print "Are you sure that you want to drop the koha database? Yes
or No?\n";
my $sure=(<STDIN>);
chop $sure;
if ($sure =~ /^Y\b|^yes|^y\b|^Yes/i) { #How sure does he need to
be? (Remove it.)
& run_drop_db_code;
}
}
print "Do you want to delete koha's users and groups? Yes or No?\n";
my $people=(<STDIN>);
chop $people;
if ($people =~ /^Y\b|^yes|^y\b|^Yes/i) { # del users & groups
& del_users_and_groups;
}
sub run_drop_db_code{
my $DBPASSWD="katikoan";
my $DBUSER="root";
if ( $DROPMODE !~ /SILENT/){
print "Please enter [mysql]database username of mysql admin
user. \n";
$DBUSER=(<STDIN>);
chop $DBUSER;
print "Please enter [mysql]database password for the mysql
admin user. \n";
$DBPASSWD=(<STDIN>);
chop $DBPASSWD;
}
my
$dbh=DBI->connect('DBI:mysql:mysql:localhost:port=3306:socket=/tmp/mysqld-new.sock',
$DBUSER, $DBPASSWD) or warn "Cannot connect to database :
$DBI::errstr\n";
my $sth = $dbh->prepare('drop database koha')
or warn "Couldn't prepare statement: " . $dbh->errstr;
$sth->execute() # Execute the query
or warn "Couldn't execute statement: " . $sth->errstr;
$sth->finish;
$dbh->disconnect;
}
sub del_users_and_groups{
foreach (@kohausers){
`$deluser $_`;
}
foreach (@kohagroups){
`$delgroup $_`;
}
}
}
sub deletelogs{
if (-d "$LOGDIR") {
my @KOHALOGS=qw( koha-access_log koha-intranet-rewrite.log
koha-opac-error_log README koha-error_log
koha-opac-access_log koha-opac-rewrite.log);
foreach (@KOHALOGS) {
print $TEE_DUAL_OUTPUT "[DELETING] $LOGDIR/$_\n";
unlink "$LOGDIR/$_";
}
rmdir ("$LOGDIR") || warn (" [ERROR IN DELETING]
$LOGDIR $?");
}
}
_______________________________________________
Koha-devel mailing list
Koha-devel@lists.koha.org
http://lists.koha.org/mailman/listinfo/koha-devel