hybiss in the year 2000 (Writing started in 1998)
Note:
Since starting this project, I have taken another position. It seems that the project might not be finished. If the machine runs on after Jan 1, 2000, all will be well, if not, I suspect that it will be replaced with a new machine.
Note:
I just (07JL98) took out all comments regarding my motivations in desiring to make this machine run past the year 2000. Many well-meaning and knowledgeable people reading this have missed the point that this is a journal kept while making an existing non-y2k compliant system work past the year 2000. It does not present a business case for doing so. They have, with good intentions, offered many good reasons to just go out and buy a new system and all new software, thus sidestepping the whole problem. That's not going to happen, and for the purposes of this report, the reasons do not matter. I will be leaving all such reasoning out of future entries as well.
- List of steps
- List of suspect programs
- List of programs replaced
- List of log files containing dates
- Listing of program to reset future file dates to current date
- Listing of program to rotate out all log files from the future
- Listing of program to set date and call the two above programs
- May 14, 1998
- May 26, 1998
- May 27, 1998
- June 1, 1998
- June 4, 1998
- June 5, 1998
- June 16, 1998
- June 19, 1998
- June 22, 1998
- June 29, 1998
- July 7, 1998
May 14, 1998, Morning
I'd gotten a bit concerned as to hybiss's readiness for the year 2000. Folklore has it that Unix machines don't have a year 2000 problem, since they keep the date as the number of seconds since January 1st, 1970. But I was concerned anyway.
Even if the kernel and filesystem are happy past the year 2000, system utilities and user applications might not be. A running kernel and filesystem don't do much good without working programs to use.
There seemed to be two possible causes of problems, utilities/applications that use 2 digit date formats in files and user interfaces, and programs that misuse the tm_year member of the tm structure. This structure is used when converting user readable dates to and from the machine readable dates, the ones that are kept as the number of seconds since 1970.
The tm_year member is defined as the number of years since 1900. When January 1st, 2000 comes along, it will switch from 99 to 100. No problems at all, that's what it's supposed to do. Unfortunately, over the years, some programmers did not read the specification, and assumed that since tm_year had always held a two digit representation of the year, that's what it was. By using it as a two digit year, they converted something that was y2k compliant into something that, in their program, was not. I've read on the 'net that HPUX 9.x will hang during reboot after the year 2000 due to an tm_year problem. I understand that 10.x does not have that problem. Remember that I read this on the 'net I have not confirmed it myself.
Wanting y2k information on a Sun SPARC running SunOS 4.1.2, naturally the first thing I did was to check Sun's web page. No luck. Sun only wants to discuss the problem for the latest version of SunOS, 4.1.3u, and then it looks as if they want a support contract.
Next I turned to Altavista and Dejanews. Many, many hits on "year 2000", "year-2000", and "y2k". Not too many on any of those "AND sunos". Few enough that I could read them all. There wasn't really any practical information available. This really surprised me. I had assumed, mistakenly, that the newsgroups, and the web would be buzzing with results from people working on "y2k remediation". I did learn that term though.
Then I looked at a lot of the many many hits that I got without "AND sunos". Only a small amount of practical information. People are just not posting their practical y2k experiences. Or perhaps everyone is still talking about it and making plans, but few are actually working on it?
Then I started reading the comp.software.year-2000, I'd seen quite a few posts to this group in my searches. Still surprisingly little practical information.
As an aside, I did discover that many people fear the effects, social and practical, of even a few systems failing, causing a domino effect and taking out otherwise functioning systems and corporations. Some real survivalist subjects keep coming up. I'm not that worried, but what I read has caused me to plan for non-functioning utilities, and various other ongoing problems, just in case. But enough of that, this article is about one computer, not the entirety of civilization.
Since it appeared that I was going to be on my own in this, I spent some time coming up with a plan to test hybiss. I knew from what I'd read that there was no way that I can completely test the system in a true post-2000 environment. I might miss something, and since hybiss is on a network, I have to be concerned about data sent and received via the network. I don't have the resources to simulate that, so I'll just have to gamble. But I can improve my odds by making sure the machine itself can run normally with its clock set past the year 2000.
The first thing I realized is that I'd need a backout plan. Once it's running with the clock set past the year 2000, files will be created with advanced dates, and log files will contain advanced dates. That's the point after all.
However, when the test is done, I'll have to bring the date back to current. Then there will be filesystem dates that are well in the future, as well as log files with dates in the future.
I decided to write a script that would use find and touch to reset any future timestamps to the current time, and to make a list of important logfiles that contained dated information. I could then rotate these log files out and resume living in the current time.
The first thing to do was to create some files with future dates to test with. Here I ran into my first conformation that SunOS 4.1.2 on hybiss is not ready for the year 2000.
The standard touch does not allow the date to be set to anything other than the current date. The sys5 version, /usr/5bin/touch does, but according to the man page, "If yy is specified, it is the last two digits of the year.". Not too encouraging.
Trying /usr/5bin/touch, I can set the dates of a file as late as December 31st, 1999, anything after that silently fatal, the date is left unchanged.
For what it's worth, I can set the year as early as 1902, 1901 or earlier fails silently. I suppose this is because time_t is a signed 32 bit integer.
I checked the man page for GNU touch (under Slackware Linux 3.4). It supports a full four digit year specification.
It looks like my first real remediation effort will be to get the source for GNU touch and compile it.
Here is quick preliminary outline of my plan, subject to a lot of potential refinement as time passes and the results start becoming clear.
0) Obtain and compile GNU touch
1) Write a script that uses find and touch to reset dates to the
present
2) Make a list of log and data files that will be seen as having
invalid future dates after the test is completed.
3) Obtain and compile the source for the latest Apache web server. I
have read that the early Apache and the ancient NCSA httpd that I
run have y2k problems, let's just get that out of the way.
4) Make a list of every utility and application that might be date
sensitive. This will be a big job, and omissions are likely.
List any files they write as well, so that they can be rotated out
or fixed after the date is set back.
5) Verify that the date command will accept dates after 1999. A
preliminary look at the man page indicates that it probably
won't. I'll probably have to look to GNU again.
6) Switch the date to late in the day, December 31st, 1999, then watch
the time roll over.
7) Try to reboot, see what happens. Maybe step 8 make this redundant.
8) Power completely down and see what happens upon start-up.
9) Test everything from step 4. This is the biggy, and will require a
lot more detail and work than this single point implies.
10) Set the date to just before midnight, February 28, then watch
the time roll over.
11) Try to reboot, see what happens.
12) Power completely down and see what happens upon start-up.
13) Repeat step 9
14) Set the date back to reality.
15) Boot into single user mode, rotate out all the system log files
identified in step 2, and run the script written in step 1
16) Switch to multiuser mode, and rotate out or repair and
applications data files with bad dates identified in step 4
Here's a very short list that's the barest start towards step 4:
gcc
make
ls
find
tar
ar
cpio
jobtrack
emacs
tin
elm
mail
mailx
pnews
mpack
lynx
plot (rasterizes plots for a versatec plotter, from Avani!, *the*
application on hybiss)
iss_spool and plot.spool (locally written support for plot)
issld (license daemon for plot)
lp
lpc
ftp (does this care about dates?)
telnet (does this care about dates?)
rlogin (does this care about dates?)
A quick look at the source for gcc and emacs shows that at least in some places, tm_year is used correctly.
This is going to be a bit of work, and I'll have justify working it into my schedule, but that will be far easier than just letting things slide and trying to justify *that* decision when things that I'm responsible for fail. Remediation at that point will eat into other's schedules as well.
What makes me nervous is multiplying this work by the number of computers that all the large corporations in the world have, then comparing that to the time that management is likely to allocate for activities that don't help the bottom line in that quarter. I'm a bit concerned.
I'm leaving on vacation tomorrow morning (15MY98), and won't be back until 26MY98. I'll probably have a real load of catching up to do then, so it might be a while until I can work in further work and updates.
May 14, 1998, Afternoon
I got a bit more time this afternoon, so I ftp'd and compiled GNU touch. It's part of the GNU fileutils package which contains:
chgrp chown chmod cp dd df du install ln dir vdir ls mkdir mvdir mkfifo mknod mv rm rmdir sync touch
I compiled them all, but initially I'm only going to install touch. Many of these utilities are used by various scripts, including rc scripts run at system startup. The less I mess with these, the better.
The new GNU touch itself does not look like it will cause any problems. The only switches that the Sun touch offers are "-c" (don't create a missing file), and "-f" (try to force the action if permissions are wrong, but ownership would let you change them). GNU touch supports both of these, as well as many more.
Does it work for dates past the year 2000? The man page said so, and my first attempt to create a file dated past the year 2000 worked fine. The standard Sun ls displayed this date correctly as well. Further tests will have to wait until after I get back from vacation.
As safe as this new touch looks, I'm not going to install it in /bin right before I go on vacation. I *do not* need an emergency call while on vacation. I'll do it when I'll be around to fix any unexpected problems.
I thought of a few more utilities that will have to be checked for y2k problems. Some probably do not use the date, I'll have to check.
chgrp chown du ld bash csh sh
May 26, 1998
OK, I just got back from vacation. It was nice, but on to y2k stuff before I get hit with a load of "real work".
First, I installed the GNU touch, compiled before vacation. I linked the old touch to touch.orig, copied the new touch to touch.foo in the same directory, then mv'd touch.foo to touch. Since mv is atomic within a given partition, this should have eliminated any chance that it might no be there, or might be partially present when a script needed it. Not a major worry, but there are a fair number of people using hybiss at a given time.
I took fewer precautions installing the man page for GNU touch. I just renamed the old page to touch_orig.1v and copied the new one to touch.1.
I waited until I got back to install the new touch, for fear of problems. One of my concerns was rebooting since a grep in /etc showed that touch is used by several rc scripts. Since too many people are using hybiss as I write this, I issued a "shutdown -r 23:59" to reboot the machine at midnight. Tomorrow morning I'll know.
I thought of a few more programs that need to be looked at:
perl (I think perl5 is OK, I've also got perl4 on hybiss, maybe all
perl4 scripts will have to be switched and tested -yuch!)
shutdown
cp (The -p option preserves times and dates)
bash (does it use dates?)
csh (does it use dates?)
I added them to the list
Now it was time to write the script to return future filesystem dates to the present. The first thing I did was to create a directory tree having a mix of dates, both future and past. I used the new touch to do this. When I made a copy to perform tests on, I discovered that cp with the -p switch is quite happy to deal with dates after year 2000. I suspect that it merely uses time_t values. Of course, when copying a file with a future date, the atime (time of last access) on the original is set to the current time, and the ctime (time of last inode change) of the new file is set to the current time. The mtime (modification time, what ls -l shows) remains as expected on both the original and new file. That's Unix.
Originally, I was going to use find and touch in a simple shell script to set dates back. My first surprise: find (even the GNU version) doesn't have any tests for files in the future. I don't know why that surprises me about the Sun version, but GNU programs usually do anything you can think of, plus a bit more. Time to whip out perl.
I wrote a perl script that I called time_back that recursively descends a file tree and sets any filesystem dates that are more than a specified time in the future back to the current time.
May 27, 1998
hybiss rebooted fine with the new GNU touch.
I made a "master list" of needed steps. Its pretty much like the list developed above, except that it will be changed and updated as needed.
I also made a list of programs to be checked. It's still pretty tentative, and consists mostly of the ones mentioned above. Again, it will be subject to changes and additions. Looking at this list, I suspect that I won't be able to do all of the testing in a single sitting (understatement!). I'll either have to take multiple trips into the future, or leave hybiss there for a while. The later is not really likely, since I'll have to be performing these tests on weekends or after hours. I certainly do not have the budget to test on a non-production machine, and hybiss is a busy little camper.
I also started a list of log files that contain dates. These will have to be rotated out of use after each test with the system time set in the future.
A load of "real work" just hit, it could be a while until I'm back to y2k testing. Oh well, 582 days to go. And only six other machines to go! The good news is that the other ones are running newer operating systems on newer hardware, and none of them is as critical as hybiss. Four of them are on my home network though, so I consider them pretty important!
June 1, 1998
I haven't had any time to work on the sun y2k problem, but on a related note, I was working with some GDSII stream files this morning, and I thought I'd look into them and see if the dates they contain are kept in a y2k compliant format.
A quick look at the file format showed that the year is kept as a signed 16 bit integer, and is good up to the year 32767. Looks good so far. Not bad for a file format developed in the 1970's.
I couldn't let it rest though. I actually looked at the data in a recently (only 5 years ago :-)) written stream file. This file was created with a modern editor, not the old Calma GDSII system that the stream format was originated on. We still use this CAD software for test circuits.
Bad news. The date was stored as 0x005d (93 in base 10) instead of a perfectly legal 0x07c9 (1993). Bummer. The date is used to mark each library and each structure within each library. These dates are definitely compared when merging the contents of a library and a stream file (a common procedure).
I decided to check a stream file that was created with a genuine Calma GDSII system (It was cool. A Data General S-280 Eclipse). No better, it kept the date as the number of years since 1900.
Of course, the CAD system would have to have been checked for y2k compliance in any case, so this is really just additional information.
While this has only glancing relevance to hybiss (the plot rasterization program was written by the same company that our newer editor was written by), it's something I'll have to address, since we'll be using these files and this software well into the next century.
June 4, 1998
I still have not been able to get back to the main task of y2k remediation on hybiss yet, but I had to do some maintenance work on two of the locally written programs, iss_plot and plot.spool. They were on my suspect list since they compare date/time to decide which plot file to rasterize first.
It turns out (I did not write these programs) that they are scripts that use "ls -lt" and "ls -ltr" on a spool directory. A quick check indicates that ls is compliant at least as far as date sorting past 2000. Some further scanning shows no other usage of dates or times in these programs.
Two down.
This doesn't clear plot rasterization, of course. At the very least, three other programs are involved, plot (binary from a CAD vendor), issld, the license daemon for plot, and lp. Perhaps more are used, but I don't think so. Yesterday I called the CAD vendor to ask about y2k compliance on hybiss and other systems where we use their stuff. It looks like purchasing new versions and support will not be a problem on our end. Hopefully the vendor is on the ball as well. I had to leave a message, so we'll see what happens.
June 5, 1998
A little free time opened up, so I looked at the "Master list". Next up was still making a list of log files containing dates. I couldn't think of any more, but I'll keep my eyes open.
Item three was "Obtain and compile the source for the latest Apache web server". Easier done than said. I got apache 1.3, the latest non-beta as I write, from http://www.apache.org/
It was only 1.1M in size and downloaded without a hitch. Thanks to the new "Autoconf-style" ( I assume that this means autoconf is not really used) setup, configuration, compilation, and installation was a breeze.
I decided to test it on port 8080 instead of port 80. Then I could test it without taking the old NCSA httpd down from port 80. This is important, as even I'm surprised by how many people use the hybiss web site. I'd hate to pull it out from under them.
The initial test displaying "It Worked! The Apache Web Server is Installed on this Web Site! " went without a hitch, I'm out of time for the moment, so I'll wait until another day to point the server at the real content and cgi-bin scripts. We'll see how portable they are then. A few months ago I copied the contents of hybiss to a Linux machine running apache. I fixed the most glaring problems then, and put the fixes back onto hybiss. Hopefully there won't be too much more to do.
June 16, 1998
I finally got the time to try all of the important cgi-bin stuff on hybiss using the new apache server. A few minor changes were made to some of the scripts when they created URL's that pointed to the primary server on port 80. Most were OK as is. Everything passed, so I changed the rc files to start the new apache, changed httpd.conf so that apache ran on port 80, then manually killed the NCSA server and restarted apache on port 80. All looked well, so I entered "shutdown -r 23:59" so that I can be sure that everything restarts fine upon reboot.
After that I worked on the list of applications, utilities, and library functions that seem most likely to fail due to date problems. I broke the list down into those categories as well.
June 19, 1998
After thinking about it a bit, I've decided that I'll have to make several trips into the future, there's just too much to do at once. Because of this, I've added another step to the list, this one to write a script to rotate out old (future) log files and then run the date-reset program written earlier. At this point, it's step 6, that might change.
After studying the date command and its man page, it's clear that it's not compliant. A little research determined that the GNU date command is in the sh-utils package. After downloading it, there was no time to compile and test it, that will have to wait.
June 22, 1998
I just compiled sh-utils-1.16, downloaded last Friday. It went fairly well. Once again, to be cautious, I manually installed the date program and its man page, but nothing else.
A quick test shows that the new date works well, both to display the date and to set it. I only tried changing the time a couple minutes, I'll leave the real y2k testing until I'm ready. :-)
I checked the rc scripts, date is only used in a few places, all without any command-line options, and all to output a date stamp to stdout. It looks like there should be no problems, but I'll set the machine to reboot at midnight just to make sure it will come up.
I just added a new list to this document. This is a list of programs/utilities/etc that have been replaced in order to make the machine y2k complient.
June 29, 1998
The reboot at midnight 22JN98 went just fine. Now I'm going to write the script covered in step 6 of the list.
July 7, 1998
The script to rotate log files is done. I decided that since I will be going into and out of the future quite a bit, I'd go one step further and write a simple shell script that would use rdate to pull the real date from another machine on the network, set the date using it, then call other two scripts to rotate out all of the log files with future dates and then recurse through the file system setting and time stamps from the future back to the present.
I decided that it was time to take a tentative trip into the future. I set the time to 23:59:50 on December 31, 1999 and watched the time tick over into 2000. GNU date reported the new date correctly. Apache 1.3 still worked. Simple commands such as 'ls' and 'cd' worked. Obviously the kernel was still working.
I executed a 'shutdown -r now'. It worked perfectly and the time reported at boot up was about ten minutes into the year 2000.
I then executed the 'wayback' script to return to the present. No problems were encountered.
Next I'll have to come up with some plans to test individual functions, utilities and applications. After that I'll have to make more trips into the future to perform these tests.
Master List of things to do
This list will be modified and updated as needed, it's still fairly tentative.0) Obtain and compile GNU touch 1) Write a script that uses find and touch to reset dates to the present 2) Make a list of log and data files that will be seen as having invalid future dates after the test is completed. 3) Obtain and compile the source for the latest Apache web server. I have read that the early Apache and the ancient NCSA httpd that I run have y2k problems, let's just get that out of the way. 4) Make a list of every utility and application that might be date sensitive. This will be a big job, and omissions are likely. List any files they write as well, so that they can be rotated out or fixed after the date is set back. 5) Verify that the date command will accept dates after 1999. A preliminary look at the man page indicates that it probably won't. I'll probably have to look to GNU again. 6) Write a script to rotate out old (future) log files and call the date reset script 7) Switch the date to late in the day, December 31st, 1999, then watch the time roll over. 8) Try to reboot, see what happens. 9) Power completely down and see what happens upon start-up. 10) Test everything from step the application/utility/function list. This is the biggy, and will require a lot more detail and work than this single point implies. 11) Set the date to just before midnight, February 28, then watch the time roll over. 12) Try to reboot, see what happens. 13) Power completely down and see what happens upon start-up. 14) Retest all items in the application/utility/function list. 15) Set the date back to reality. 16) Boot into single user mode, rotate out all the system log files and reset all filesystem dates with the script written earlier.
List of suspect programs
This list will be updated quite a bit before it's ready to use. It's still very tentative. Some programs in it are probably not date-aware, but if there's any doubt, I'll look into it. Some that do use dates will just use time_t values. I'll be in my mid '70s before that is a problem. Hey, isn't that how we got into this in the first place... :-)
Library functions: asctime(3) ctime(3) dysize(3) gmtime(3) localtime(3) strptime(3)
Utilities:
ar
at
atq
bash
bash
chgrp
chown
cp (The -p option preserves times and dates)
cpio
cron
csh
csh
du
dump
elm
emacs
find
ftp
gcc
last
ld
lp
lpc
ls --- -lt switches work ---
lynx
mail
mailx
make
mpack
/usr/lib/newsyslog
perl (I think perl5 is OK, I've also got perl4 on hybiss, maybe
all perl4 scripts will have to be switched and tested -yuch!)
rdate
rlogin
sh
shutdown
tar
telnet
tin
uptime
who
Applications: iss_spool *** Checks out OK*** issld jobtrack (seems to use 2 digit dates in its log) plot plot.spool *** Checks out OK*** pnews transmission
List of programs which have been replaced
/bin/touch Replaced with touch from GNU fileutils-3.16, obtained
from ftp://prep.ai.mit.edu The original program was renamed
to touch.orig, and the original man page was was renamed from
touch.1v to touch.orig.1v
/bin/date Replaced with date from GNU sh-utils-1.16, obtained from
ftp://prep.ai.mit.edu The original program was renamed to
date.orig, and the original man page was renamed from
date.1v to date.orig.1v
List of log files which contain dates
/var/adm/messages (does not contain years, just month, day, time, cron
uses newsyslog on this every Saturday in any
case)
/var/log/syslog (No years here either)
/var/adm/plotter.log (does contain year, is it ever read, or is it
write-only?)
/var/adm/wtmp (definitely a concern)
/var/adm/lastlog
/etc/utmp (would probably take care of itself)
/var/log/syslog (does not contain years, just month, day, time)
~web/logs/access
~web/logs/jobtrack_log
~web/logs/error_log
~web/logs/num_log
~web/logs/db_log
~web/logs/transmision/transmission_log
Listing of program used to set file dates back to the present
This script uses perl5 and runs under SunOS. It's not super-spiffy, it's what you get when you write code as fast as you can type... :-)
I call it time_back
Just a reminder: THIS PROGRAM DOES NOT FIX Y2K PROBLEMS, that's a job for humans. All it does is set future dates on files back to the present while skipping files with dates in the present or past.
#!/usr/bin/perl5 -w
# Jim Buchanan, c22jrb (at) dawg.delcoelect.com, jbuchana (at) iquest.net
# This program uses perl 5 It is written to run under SunOS 4.1.2
# and makes some definite assumptions. Basically, it was written
# as fast as I could type, since I've got lots of other stuff to do
# I did go back and add comments when I got it running though.
# this is how far in the future a file needs to be
# before we worry about it. We want it to be at least
# a few minutes, so that we don't catch files changed
# since this program started, but it has to be before
# y2k. In mid 1998, I'll use a year.
# This is in seconds.
$allowed_offset = 1 * 365 * 24 * 60 * 60;
$ENV{PATH} = "/bin:/usr/bin:/usr/local/bin:/usr/ucb:/etc";
# For testing purposes, allow the user to specify a root directory
# on the command line. In real use, none will be used and the entire
# system will be scanned
if (defined (@ARGV))
{
$root_dir = shift @ARGV;
# If a non-fully-qualified path is supplied, fully qualify it
# Things like /foo/./foo work fine
if ($root_dir !~ m:^/:)
{
$cwd = `pwd`;
chomp ($cwd);
$root_dir = $cwd . "/" . $root_dir;
}
}
else
{
$root_dir = "/";
}
# Calculate the threshold time after which we'll declare a file to be
# "in the future"
$threshold_time = time () + $allowed_offset;
# Create an array holding the mount points for NFS filesystems,
# we do not want to traverse them
find_nfs_mounts ();
# do the real work
recurse_dirs ($root_dir);
###########################################################################
# Subroutines from here down
# The real work is done here
sub recurse_dirs
{
my ($current_dir);
my ($current_file);
local (*IN_DIR);
# I really hate using $_[0] etc., this way it only has to be
# done once per subroutine
$current_dir = $_[0];
# open the specified directory
unless (opendir (IN_DIR, $current_dir))
{
die "***ERROR*** Could not open '$current_dir' with opendir, $!\n";
}
# read the directory entries one at a time
# if the entry is a directory itself, call recurse_dirs again
while (defined ($current_file = readdir (IN_DIR)))
{
# we want full path names, it makes looking for nfs mounts easier
$current_file = $current_dir . '/' . $current_file;
# this function allows us to skip ".", "..", nfs mounts, and symbolic links
if (good_file ($current_file))
{
# if the entry is in the future, fix it
if (future_date ($current_file))
{
re_date ($current_file);
}
# if the entry is a directory itself, call recurse_dirs recursively
if (-d $current_file)
{
recurse_dirs ($current_file);
}
}
}
# close the directory
closedir (IN_DIR);
}
# Check the directory entry, we don't want ".", "..", nfs mounts,
# or symbolic links
sub good_file
{
my ($basename);
my ($pathname);
my ($nfs_mount);
# I still don't like this!
$pathname = $_[0];
# It's a symbolic link
if (-l $pathname)
{
return (0);
}
# find the base name of the file, no path before it
$basename = $pathname;
$basename =~ s:.*/::;
# It's "." or ".."
if (($basename eq ".") || ($basename eq ".."))
{
return (0);
}
# It's an nfs mount point
foreach $nfs_mount (@nfs_mounts)
{
if ($pathname =~ m:$nfs_mount:)
{
return (0);
}
}
# It's an OK file
return (1);
}
# We need a list of nfs mount points, as we don't want to even think
# about going there
sub find_nfs_mounts
{
my (@raw_lines);
my ($line);
# This assumes that "mount" is on your path, and that its behavior
# is the same as the mount supplied with SunOS 4.1.2. That's risky if
# you try to use this on another system w/o checking
# This will not work under HPUX 9.05
# Slackware Linux 3.4 looks like it is close enough that it might work
@raw_lines = `mount`;
# look at each line that mount outputs
foreach $line (@raw_lines)
{
chomp ($line);
# We only want lines that talk about nfs mounts
# HPUX 9.05 does not mention nfs in its basic
# mount messages
if ($line =~ /type nfs/)
{
# parse the line to extract the mount point
# Isn't perl great?
$line =~ s:.*on (/[^\s]*).*:$1:;
push (@nfs_mounts, $line);
}
}
}
# Test to see if any of the file dates are in the future
# atime is the time of last access, probably not too important,
# but we'll fix it anyway. cat-ing out the file changes this
# as does making a copy (it changes the original that is)
# ls -lu displays this time
# mtime is the time of last file modification. This is what ls -l
# displays
# ctime is the time that the information in the inode was last
# change, *not* the file creation time. for instance, chmod
# will change this. This is the time that ls -lc displays
sub future_date
{
my ($file_name);
my ($atime);
my ($mtime);
my ($ctime);
# We hates it, don't we my precious?
$file_name = $_[0];
# stat the file to find the times
($atime, $mtime, $ctime) = (stat ($file_name))[8,9,10];
# it lives in the future!
if (($atime > $threshold_time) ||
($mtime > $threshold_time) ||
($ctime > $threshold_time))
{
return (1);
}
# it's a somal god-fearing file that lives in the present and past
return (0);
}
# Actually change the time
# The documentation for GNU touch only mentions that atime and mtime are changed.
# My testing seems to indicate that the ctime is changed as well, but only
# to the current time. Oh well, that's what we want. I was afraid that I'd
# have to do something to the inode (such as a chmod) to get this to work,
# but I won't have to.
# Note that I had to compile GNU touch before I even wrote this program. The
# touch supplied with SunOS 4.1.2 would not let me set file dates past midnight,
# December 31st, 1999, making testing harder
sub re_date
{
my ($file_name);
# We hates the Baggins!
$file_name = $_[0];
# once again, we assume that touch is on your path
system ("touch $file_name");
}
Listing of program used to rotate out log files
Once again, this script uses perl5 and runs under SunOS. It's not perfect, it's what you get when you write code as fast as you can type... :-)
I call it rotate_logs
Just a reminder: THIS PROGRAM DOES NOT FIX Y2K PROBLEMS, that's a job for humans. All it does is rotate out log files that might contain future dates.
#!/usr/bin/perl5 -w
$ENV{PATH} = "/bin:/usr/bin:/usr/local/bin:/usr/lib/";
# Keep people from logging in while we're doing this.
$nologin = "/etc/nologin";
if (system ("touch $nologin"))
{
die "***ERROR*** Could not 'system (\"touch $nologin\")', $!\n";
}
# Use Sun-Supplied newsyslog here
# to rotate /var/adm/messages and /var/log/syslog
$newsyslog = "newsyslog";
print STDERR "About to rotate system logs with $newsyslog\n";
if (system ("$newsyslog"))
{
cleanup_n_die ("***ERROR** Could not 'system (\"$newsyslog\"), $!\n");
}
print STDERR "Done!\n";
# Remove and replace plotter.log, I don't like
# these permissions, but I didn't write the plot
# software that dies without them
remove_replace ("/var/adm/plotter.log", "0666", 0, 10);
# remove and replace wtmp
remove_replace ("/etc/wtmp", "0644", 0, 10);
# remove and replace lastlog
remove_replace ("/var/adm/lastlog", "0644", 0, 10);
# remove and replace utmp
remove_replace ("/etc/utmp", "0664", 0, 10);
# remove and replace /home2/httpd/logs/transmission/transmission_log
remove_replace ("/home2/httpd/logs/transmission/transmission_log", "644", 120, 22);
# Check to see if apache is running. If it is, the extension on the
# lock file is the PID, save it.
$apache_lock = <lt;/usr/local/apache/var/run/httpd.lock*>;
$apache_pid = -1;
if (defined ($apache_lock))
{
$apache_pid = $apache_lock;
$apache_pid =~ s:.*lock\.::;
print STDERR "Apache lock file name is '$apache_lock'\n";
print STDERR "Apache PID is '$apache_pid'\n";
}
# remove and replace access_log (Apache log file)
remove_replace ("/usr/local/apache/var/log/access_log", "644", 0, 1);
# remove and replace error_log (Apache log file)
remove_replace ("/usr/local/apache/var/log/error_log", "644", 0, 1);
# Send HUP to any running apache to restart it This is so that it uses
# the new log files
if (defined ($apache_lock))
{
unless (kill 1, $apache_pid)
{
cleanup_n_die ("***ERROR*** Could not 'unless (kill 1, $apache_pid)', $!\n");
}
}
# jobtrack_db will re-read its table if sent a HUP, but since it logs to
# stderr, which is then redirected to the log file in the rc script that
# starts it, we have to kill and restart the entire server. It responds to TERM
# gracefully,so we can kill it that way, then restart it with its rc script
kill_n_restart ("jobtrack_db", "/home2/httpd/logs/jobtrack_log", "/etc/rc.jobtrack");
# Like jobtrack_db, req_num_server will respond to TERM gracefully,so
# we can kill it that way, then restart it with its rc script
kill_n_restart ("req_num_server", "/home2/httpd/logs/num_log", "/etc/rc.num");
# req_db_server is similar as well
kill_n_restart ("req_db_server", "/home2/httpd/logs/db_log", "/etc/rc.db");
# if $nologin exists, delete it
if (-f $nologin)
{
unless (unlink ("$nologin"))
{
print STDERR "***ERROR*** Could not 'unlink (\"$nologin\")', $!\n";
}
}
###########################################################################
# Subroutines from here down
sub remove_replace
{
my ($file_name);
my ($mode);
my ($owner);
my ($group);
# I really hate using $_[N] any further in than this
$file_name = $_[0];
$mode = $_[1];
$owner = $_[2];
$group = $_[3];
print STDERR "About to remove and replace '$file_name'\n";
# If $file_name exists, delete it
if (-f "$file_name")
{
unless (unlink ("$file_name"))
{
cleanup_n_die ("***ERROR*** Could not 'unlink (\"$file_name\"), $!\n");
}
}
# recreate $file_name
if (system ("touch $file_name"))
{
cleanup_n_die ("***ERROR*** Could not 'system (\"touch $file_name\")', $!\n");
}
# set the mode of $file_name
unless (chmod oct ($mode), $file_name)
{
cleanup_n_die ("***ERROR*** Could not 'chmod " . oct ($mode) . ", $file_name', $!\n");
}
# set ownership of $file_name
unless (chown $owner, $group, $file_name)
{
cleanup_n_die ("***ERROR*** Could not 'chown $owner, $group, $file_name', $!\n");
}
print STDERR "Done!\n";
}
sub get_process_pid
{
my ($process_name);
my (@pids);
my ($current_pid);
my ($found_it);
my ($returned_pid);
my ($rest);
# I still don't like this
$process_name = $_[0];
# If no process is found, we'll return a -1
$returned_pid = -1;
# Read in the output of ps
@pids = `ps -ax`;
# Look for the process in the table
$found_it = 0;
foreach $current_pid (@pids)
{
chomp ($current_pid);
if ($current_pid =~ /$process_name/)
{
$found_it++;
$returned_pid = $current_pid;
$returned_pid =~ s/^ *//;
$returned_pid =~ s/ .*//;
}
}
# This program is quick and dirty, if we run into simething really unexpected,
# it has to be hand-fixed
if ($found_it > 1)
{
cleanup_n_die ("***ERROR*** More than one ($found_it) process matches '$process_name'\n");
}
return ($returned_pid);
}
sub kill_n_restart
{
my ($process_name);
my ($logfile_name);
my ($rc_script);
my ($process_pid);
# Since I don't like $_[N]
$process_name = $_[0];
$logfile_name = $_[1];
$rc_script = $_[2];
print STDERR "About to kill $process_name, delete '$logfile_name', and restart $process_name with $rc_script\n";
# Get the process ID for jobtrack_db
$process_pid = get_process_pid ("$process_name");
print STDERR "$process_name PID is '$process_pid'\n";
# If the PID exists, kill the process
if ($process_pid > 0)
{
unless (kill 15, $process_pid)
{
cleanup_n_die ("***ERROR*** Could not send signal to pid $process_pid, $!\n");
}
}
# Delete $logfile_name if it exists
if (-f $logfile_name)
{
unless (unlink ("$logfile_name"))
{
cleanup_n_die ("***ERROR*** Could not 'unlink (\"$logfile_name\"), $!\n");
}
}
# Start new process
if (system ("$rc_script"))
{
cleanup_n_die ("***ERROR** Could not 'system (\"$rc_script\"), $!\n");
}
print STDERR "Done!\n";
}
sub cleanup_n_die
{
my ($epitaph);
# As good a name as any
$epitaph = $_[0];
print STDERR "$epitaph";
# if $nologin exists, delete it
if (-f $nologin)
{
unless (unlink ("$nologin"))
{
print STDERR "***ERROR*** Could not 'unlink (\"$nologin\")', $!\n";
}
}
die "\n";
}
Listing of program used to set the date, rotate out log files and reset file dates
This is a simple shell script that sets the date to match another system, then calls the other two programs which rotate log files and set the time stamps on files.
I call it 'wayback'.
Just a reminder: THIS PROGRAM DOES NOT FIX Y2K PROBLEMS, that's a job for humans. All it does is set the system time and call two other programs.
#!/bin/bash PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin # set the date from a workstation that lives in the present day rdate kopt0017 # rotate out all logs that might have a future date in them rotate_logs # find any files created in the future and set the dates to the present time_back



