Tag Archives: unix

IBM RS/6000 von 1993

Von den Leuten, die uns “STRG”, “ENTF” und “EINFG” gebracht haben, ein Highlight, das sich leider nie durchgesetzt hat: Die GRDST-Taste.

Diese RS/6000 hat den Weg zu mir so um 2000 gefunden, als mein erster Vollzeit-Linuxjob noch ein paar Jahre entfernt war.

Damals kuschelte IBM etwas widerwillig mit Linux und hatte auf AIX 4.3.3 parallel zur Einführung von AIX 5L (das L sollte für die Nähe zu Linux stehen) RPM als additiven Paketmanager eingeführt. Die Liste der damals verfügbaren Pakete kann bei bullfreeware.com bewundert werden (hier ein lokaler Mirror). Ich habe zuletzt noch einige davon installiert, um das Tool zum Benchmarking übersetzen zu können.

Zur 7012 besitze ich auch noch das passende SCSI-CDROM mit der passenden obskuren Blockgröße. Installationsmedien sind aber keine mehr vorhanden. Die Demo-Installation mit User root und Password root muss also für immer halten. Außer AIX ist mir kein Betriebssystem bekannt, das auf dem System nutzbar wäre.

SSH fehlt, aber per Telnet über den wackeligen AUI-Transceiver mit 10 Megabit/s macht das System einen sehr guten und responsiven Eindruck, fast besser als heute manche VMware-Instanz. 😉

Die Towers of Hanoi aus dem BYTE Unix Benchmark führt die RS/6000 mit ca. 1050 Loops pro Sekunde aus. Ein halbwegs aktuelles Vergleichssystem mit Intel-CPU und 3,6 GHz kommt auf ca. 3200000 Loops pro Sekunde.

Divisionen in der folgenden Schleife macht die RS/6000 mit 16500/s (Perl 5.5 vorinstalliert) bzw. 14500/s (Perl 5.8 aus dem RPM); mein moderneres Vergleichssystem kommt auf knapp 7 Millionen/s.

perl -e '$o=time();$s=$o;while(10>$o-$s)
{rand()/(rand()+1);$i++;$n=time();if($n!=$o)
{printf"%i\n",$i;$i=0};$o=$n}'

Softwaretechnisch größtes Highlight dürfte das installierte Java 1.1.8 sein. IPv6 wird zur Konfiguration angeboten, funktioniert aber in dieser aus dem Jahr 1999 stammenden Implementation nicht wirklich zufriedenstellend.

Technische Daten: POWER1-Prozessor mit 50 MHz, 128 MB Arbeitsspeicher, 2 GB Festplatte. Produktionszeitraum 1993-1994. (Mirror vom Datenblatt)

(Dieser Beitrag stand 2014 schon mal an anderer Stelle. Die Benchmarks auf heutigen Systemen wurden aktualisiert und ein lokaler Mirror der Bullfreeware-Liste und des Datenblatts gesichert.)

How expiration dates in the shadow file really work

tl;dr: Accounts expire as soon as UTC reaches the expiration date.
In today‘s installment of my classic shame-inducing series “UNIX basics for UNIX professionals”, I want to talk about account (and password) expiration in /etc/shadow on Linux.
The expiration time is specified as days since january 1st, 1970. In the case of account expiration, the according value can be found in the second to last field in /etc/shadow.
Account expiration can be configured using the option „-E“ to the „chage“ tool. In this case, I want the user „games“, which I‘ll be using for demonstration purposes, to expire on the 31st of december, 2017:

# chage -E 2017-12-31 games

Using the „-l“ option, I can now list the expiration date of the user:

# chage -l games
[…]
Account expires : Dec 31, 2017
[…]

The first thing to be taken away here is that, as I can only use a number of days, I can not let a user expire at any given time of day. In /etc/shadow, I have now:

# getent shadow | awk -F: '/^games:/{print $8}'
17531

This of course can to be converted to a readable date:

# date --date='1970-01-01 00:00:00 UTC 17531 days'
Sun Dec 31 01:00:00 CET 2017

So, will the account still be usable on december 31st? Let‘s change it‘s expiration to today (the 7th of July, 2017) to see what happens:

# date
Fri Jul 7 12:58:32 CEST 2017
# chage -E today games
# chage -l games
[…]
Account expires : Jul 07, 2017
[…]
# su - games
Your account has expired; please contact your system administrator
[…]

I’m now only left with the question whether this expiration day is aligned on UTC or local time.

# getent shadow | awk -F: '/^games:/{print $8}'
17354
# date --date='1970-01-01 00:00:00 UTC 17354 days'
Fri Jul 7 02:00:00 CEST 2017

I‘ll stop my NTP daemon, manually set the date to 00:30 today and see if the games user has already expired:

# date --set 00:30:00
Fri Jul 7 00:30:00 CEST 2017
# su - games
This account is currently not available.

This is the output from /usr/sbin/nologin, meaning that the account is not expired yet, so I know for sure that the expiration date is not according to local time but to UTC.
Let‘s move closer to our expected threshold:

# date --set 01:30:00
Fri Jul 7 01:30:00 CEST 2017
# su - games
This account is currently not available.

Still not expired. And after 02:00:

# date --set 02:30:00
Fri Jul 7 02:30:00 CEST 2017
# su - games
Your account has expired; please contact your system administrator

So, in order to tell from a script whether an account has expired, I simply need to get the number of days since 1970-01-01. If this number is greater or equal to the value in /etc/shadow, the user has expired.

DAYSSINCE=$(( $(date +%s) / 86400 )) # This is days till now as per UTC.
EXPIREDAY=$(getent shadow | awk -F: '/^games:/{print $8}')
if [[ $DAYSSINCE -ge $EXPIREDAY ]] # Greater or equal
then
    EXPIRED=true
fi

One last thought: We’ve looked at a time zone with a small offset from UTC. What about timezones with larger offsets, in the other direction?

  • If we move the timezone to the east, further into the positive from UTC, it will behave the same as here in CEST and the account will expire sometime during the specified day, when UTC hits the same date.
  • If we move the timezone far to the west, like e.g. PST, and an absolute date is given to “chage -E“, the account will probably expire early, the day before scheduled expiration. I was not able to find anything useful on the web and even my oldest UNIX books from the 1990s mention password expiration only casually, without any detail. Active use of password expiration based on /etc/shadow seems to be uncommon. The code that seems to do the checking is here and it does not appear to care about time zones at all.
  • Any comments that clarify the behaviour in negative offsets from UTC will be appreciated.

What does the slash in crontab(5) actually do?

That’s a bit of a stupid question. Of course you know what the slash in crontab(5) does, everyone knows what it does.
I sure know what it does, because I’ve been a UNIX and Linux guy for almost 20 years.
Unfortunately, I actually didn’t until recently.
The manpage for crontab(5) says the following:
20141017150008
It’s clear to absolutely every reader that */5 * * * * in crontab means, run every 5 minutes. And this is the same for every proper divisor of 60, which there actually are a lot of: 2, 3, 4, 5, 6, 10, 12, 15, 20, 30
However, */13 * * * * does not mean that the job will be run every 13 minutes. It means that within the range *, which implicitly means 0-59, the job will run every 13th minute: 0, 13, 26, 39, 52. Between the :52 and the :00 run will be only 8 minutes.
Up to here, things look like a simple modulo operation: if minute mod interval equals zero, run the job.
Now, let’s look at 9-59/10 * * * *. The range starts at 9, but unfortunately, our naive modulo calculation based on wall clock time fails. Just as described in the manpage, the job will run every 10th minute within the range. For the first time at :09, after which it will run at :19 and subsequently at :29, :39, :49 and :59 and then :09 again.
Let’s look at a job that is supposed to run every second day at 06:00 in the morning: 0 6 */2 * *. The implied range in */2 is 1-31, so the job will run on all odd days, which means that it will run on the 31st, directly followed by the 1st of the following month. The transitions from April, June, September and November to the following months will work as expected, while after all other months (February only in leap years), the run on the last day of the month will be directly followed by one on the next day.
The same applies for scheduled execution on every second weekday at 06:00: 0 6 * * */2. This will lead to execution on Sunday, Tuesday, Thursday, Saturday and then immediately Sunday again.
So, this is what the slash does: It runs the job every n steps within the range, which may be one of the default ranges 0-59, 0-23, 1-31, 1-11 or 0-7, but does not carry the remaining steps of the interval into the next pass of the range. The “every n steps” rule works well with minutes and hours, because they have many divisors, but will not work as expected in most cases that involve day-of-month or day-of-week schedules.
But we all knew this already, didn’t we?