Uppdaterat 2014.09.29, av Kristoffer

För ett tag sedan var jag tvungen att använda mig utav Perl för att generera användare och sedan ge dem ett tillfälligt lösenord som de kommer att få byta när de har loggat i. Systemet där skriptet användes är ett Linux-system (CentOS 6.5).

Skriptet matchar följande krav:

  • Ha stöd för utf-8
  • Läsa in för- och efternamn från en textfil
  • Skapa unika användare från textfilen
  • Skriva ut användarinformation till en ny textfil per användare, i en särskild mapp

För att kunna köra skriptet krävs modulen Text::Iconv, vilket kan testas genom att skriva perl -e 'use Text::Iconv;' i kommandotolken. Om du inte får ett svar, är modulen installerad. Om du får många felmeddelanden som svar, är modulen inte installerad. Hur man installerar moduler kan jag skriva om i ett annat inlägg, annars kan ni använda det ”gamla” sättet (vad gäller mitt skript) där icke-ASCII-tecken blir bytta till ett x. Eventuellt kan du kika på denna hemsida som förklarar hur man installerar ett verktyg som kan vara till stor hjälp i en CentOS-maskin, på engelska. Vidare står här hur man sedan använder verktyget för att installera modulerna.

Om du undrar över något, går det att skicka in ett mail till mig, så ska jag försöka svara så fort jag kan. Eventuellt, om det är flera som frågar, kan jag publicera svaren här i detta inlägg eller någon annanstans på hemsidan. Dock kommer skriptet inte att kontrollera om användaren lägger till mer input än vad som behövs.

För att få denna kod att vara såpass internationell som möjligt, används engelska kommentarer och variabelnamn.

#!/bin/usr/perl
#############METADATA############
# Author:	Kristoffer Qvist
# Version:	2
# Last
# Modified:	Sep 29th, 2014
# History:	Made utf-8 to
# 		ASCII converting
#		better.
#################################

use warnings;
use strict;
use Text::Iconv;

binmode STDOUT, 'utf8';

# Get file that contains users
my ($file, $userDir) = @ARGV;

while(not -e $file) {
    print("Please, add a valid file containing your users.\n");
    chomp($file = <STDIN>);
}

while(not -e $userDir) {
    print("Please, add a valid folder to store the user password files\n");
    chomp($userDir = <STDIN>);
}

# A basic check for script injection attempt
if($file =~ /;/ or $userDir =~ /;/) {
    die("Script injection attempt found!\n");
}

# Put all new users in array
open(USERS, "<", $file) or die("The file $file could not be opened: $!");
chomp(my @new_users=<USERS>);
while (<USERS>) {
    push (@new_users, $_);
}
close USERS or die($!);

# Get passwd content
my $passwd_file     = "/etc/passwd";
my $passwd_contents = open(PASSWD, "<", "/etc/passwd") or die("$!");
my @passwd;
while (<PASSWD>) {
    push (@passwd, $_);
}
close PASSWD or die("$!");

# Set all existing users in hash
my %existing_users = ();
for(my $i=0;$i<scalar(@passwd);$i++) {
    my @passwd_entry = split /:/,$passwd[$i];
    $existing_users{$passwd_entry[0]} = $i;
}

# Add users to the system and create a random one-time password
foreach my $new_user(@new_users) {
    my @names = split(/ /, $new_user); 

    my $fn = substr($names[0],0,3);
    my $ln = substr($names[1],0,2);

    my $username = $fn.$ln;

    # Converts non-ascii to x (old; latter converting is better)
    # $username =~ s/[^[:ascii:]+]/x/g; 

    # Encode usernames to ascii (new)
    my $convert_this = Text::Iconv->new("UTF-8", "ASCII//TRANSLIT");
    $username = $convert_this->convert($username);
    $username = lc($username);

    # Check for duplicate users, if found add number 
    my $i = 1;
    while(exists $existing_users{$username}) {
        $username =~ s/[0-9]//g;
        $username = $username.$i++;
    }
    $existing_users{$username} = $i;
    my $password = join'', map +(0..9,'a'..'z','A'..'Z','!?()""')[rand(10+26*2)], 1..8;
    `useradd $username -c "$new_user" &> /dev/null`;
    `echo -e "$password\n$password" | passwd $username &> /dev/null`;
    `chage -d 0 $username`;
    open (USERFILE, ">", "$userDir/$username.txt") or die("The file $userDir/$username.txt could not be opened: $!\n");
    print USERFILE "$new_user\n--------------------\n$username: $password";
    close USERFILE or die("The file $userDir/$username.txt could not be closed: $!\n");
}
print("\nBatch completed!\n");