Archiv der Kategorie: Software

Alles was mit Software zu tun hat

s3cmd: Instabile Verbindung bei PUT

s3cmd ist ein kleines CLI-Tool, welches die Verwaltung von Amazon S3 ermöglicht. Beim hochladen von Dateien mit der Version 1.0.1 aus dem Paketmanager zeigte sich jedoch folgendes Bild:

WARNING: Upload failed: test ([Errno 32] Broken pipe)
WARNING: Retrying on lower speed (throttle=1.25)
WARNING: Waiting 15 sec...
test -> s3://testbucket/test  [1 of 1]
       1234 of 5678     0% in    1s     1.23 kB/s  failed
ERROR: Upload of 'test' failed too many times. Skipping that file.

Ursache ist in meinem Fall, dass mein Bucket nicht in „USA Standard“ liegt. Ältere Versionen von s3cmd greifen jedoch immer dort zu. Zwar leitet Amazon den Request passend um, hierbei scheint sich das Tool jedoch zu verschlucken.

Beheben lässt sich der Fehler auf 2 Arten: Entwerden man nutzt eine neuere Version des Tools, z.B. 1.5.2, diese müssen jedoch meist manuell installiert werden und sind nicht in den Quellen der Paketmanager zu finden. Alternativ kann man der alten Version auf die Sprünge helfen, in dem man die Server direkt richtig hinterlegt, für Irland z.B.:

[default]
...
bucket_location = IE
...
host_base = s3-eu-west-1.amazonaws.com
host_bucket = %(bucket)s.s3-eu-west-1.amazonaws.com
...
use_https = True
    

Apache als Reverse Proxy

Apache ist als Webserver den meisten bekannt, mit der üblicherweise mitgelieferten mod_proxy_html kann er jedoch auch als reverse Proxy eingesetzt werden. Ein solcher Proxy nimmt HTTP-Anfragen entgegen und leitet sie an einen anderen Weberver weiter. Dies kann z.B. hilfreich sein um Anfragen auf mehrere Server im Hintergrund zu verteilen, eine zusätzliche Abschottung interner Server bereitstellen oder auch durch die Terminierung der HTTPS-Verbindung oder dem Vorfiltern von Headern die Belastung der nachgeschalteten Systeme zu mindern.

Zur Konfiguration stellt man erst sicher, dass das Modul geladen ist. Hierzu wird in der Apache-Konfiguration (Arch Linux: /etc/httpd/conf/httpd.conf) sichergestellt, dass die folgenden Zeilen aktiv sind:

LoadModule xml2enc_module modules/mod_xml2enc.so
LoadModule proxy_html_module modules/mod_proxy_html.so

Nun kann im gewünschten VHost eine passende Weiterleitung realisiert werden:

#Nur definierte Requests annehmen
ProxyRequests Off

#Fileshare
ProxyPass /dateiserver http://publicfiles.lan.adlerweb.info/upload
ProxyPassReverse /dateiserver http://publicfiles.lan.adlerweb.info/upload

#Requestform
ProxyPass /request https://http.lan.adlerweb.info/request
ProxyPassReverse /request https://http.lan.adlerweb.info/request

#Buildimg
ProxyPass /autobuild https://inferno.lan.adlerweb.info/results
ProxyPassReverse /autobuild https://inferno.lan.adlerweb.info/results

Wenn das interne Ziel per HTTPS angesprochen werden soll, so sollte die jeweilige Zertifizierungsstelle im System bekannt sein. Hierzu kann auch eine eigene CA-Datei verwendet werden:

SSLProxyCACertificateFile /etc/ssl/private/interneca.crt

Wenig Zeilen, große Wirkung: Surft man nun die angegebenen Pfade des Webservers an, so wird die Anfrage an den angegebenen Server weitergeleitet. Der Apache selbst terminiert hierbei die Clientverbindung, entsprechend werden Funktionen (z.B. externes HTTPS-Zertifikat) verwendet. Auch DoS-Angriffe oder versuche mit kaputten HTTP-Headern treffen primär den exponierten Server und schlagen nicht ohne Weiteres zum internen Webserver durch.

Update: ProxyRequests Off fehlte – wenn auf On agiert der Server als offener Proxy-Server. Default ist Off, daher sollte auch ohne explizites definieren nichts passieren, aber vorsichtshalber kann es nichts schaden hier nochmal zu definieren.

Squid als Proxy-Server

„Mein Internet ist kaputt“ – ich denke jeder 1st-Leveler kennt diese Aussagen. Bauchschmerzen bereiten sie spätestens dann, wenn auch man selbst nicht mehr ins Netz kommt. Proxy weg. In solchen Situationen muss schnelle Hilfe her. Mein erster Blick: Da steht noch ne Testkiste – zwar ist Arch Linux nicht unbedingt die erste Wahl für Produktivserver, welche möglichst wartungsarm sein sollen, aber besser als nichts. Bauen wir mal einen Proxy.

1. Squid installieren

Die Platzhirsch unter den Proxys dürfte ohne Frage Squid sein. Die GPL-Software kann sowohl als Caching als auch Reverse Proxy eingesetzt werden. Ich nutze nur die erste Funktion – Zugriffe der Benutzer sollen zwischengespeichert werden. Die Installation ist unter nahezu allen Distributionen mit wenigen Schritten über den Paketmanager möglich. In meinem Fall reicht ein „pacman -S squid“.

2. Zugriffs- und Speicherkonfiguration

Neben der Software wird auch eine Standardkonfiguration installiert, welche unter /etc/squid/squid.conf zu finden ist. Standardmäßig wird den privaten IPv4-Bereichen erlaubt auf die üblichen Ports für HTTP, FTP, Gopher, Wais und HTTPs zu verbinden. Sofern man keine restriktive Webzugriffslinie besitzt können diese Beispiele also übernommen werden. Einige Änderungen und Ergänzungen können allerdings Hilfreich sein:

# Keine Verbindung zu localhost - schuetzt ggf. falsch eingerichtete Webanwendungen auf dem Server
http_access deny to_localhost

#E-Mail-Adresse des Admins - so kommen die Beschwerden der Nutzer an die richtige Stelle
cache_mgr info@ad....fo

#Beim Stoppen des Dienstes 10 Sekunden darauf warten laufende Uebertragungen abzuschliessen
shutdown_lifetime 10 seconds

#Im RAM werden bis zu 4 GB als Cache genutzt
cache_mem 4096 MB

#Objekte mit mehr als 50MB werden nicht gecached
maximum_object_size 50 MB

# Bis 95% Fuellstand des Caches werden keine Objekte ersetzt
cache_swap_low 95

# Je naeher wir an 98% kommen desto aggressiver werden alte Objekte ersetzt
cache_swap_high 98

#Alles ueber 512kb wird nicht im RAM sondern nur auf HDD gespeichert
maximum_object_size_in_memory 512 KB

# HDD-Cache Typ aufs (async), Ordnerangabe, 32GB, Ordner erste Ebene, Ordner zweite Ebene
cache_dir aufs /var/cache/squid 32768 32 256

#Eyecandy
visible_hostname proxy.lan.adlerweb.info

#Boese Seiten
acl bad_url dstdomain "/etc/squid/bad-sites.acl"
http_access deny bad_url

#Interne IP des Clients nicht nach draussen senden
forwarded_for off

In meinem Fall musste auch der Standardport dran glauben, stattdessen wird nun 8080 verwendet, welches dem Altsystem entspricht und lästiges Umkonfigurieren erspart:

http_port 8080

3. Diktator-Modus

In der Konfiguration schimmert es schon etwas durch: I aim to misbehave. Da es sich um mein Netz handelt greifen auch meine Zensurrichtlinien. Unter /etc/squid/bad-sites.acl liegt eine Liste mit Domains, welche vom Proxy gesperrt werden. Dies kann z.B. sinnvoll sein um Werbung oder die Ziele quasselfreudiger Programme auszusperren. Dabei solltet ihr natürlich das alte Credo beherzigen: With great power comes great responsibility.

.facebook.com
.facebook.de
.google-analytics.com
.googleadservices.com
[...]

4 Minuten Später
…ist der Proxy installiert und das Internet läuft wieder. Job erledigt, wenden wir uns wieder den Katzenvideos zu.

Und sonst?
Wer es etwas weiter treiben möchte: SquidGuard oder Dansguardian können Webseiten nach Themenbereichen sperren. SquidClamav kann die aufgerufenen Webseiten auf Viren prüfen. Sarg verwandelt das Log in einen praktischen HTML-Report mit Top-Usern und den Beliebtesten Webseiten. Ansonsten hat auch sicher die Suchmaschine der Wahl noch genügend Ideen zur Freizeitvernichtung.

Linux: Partitionen innerhalb einer Image-Datei/LV mounten

Bisher speicherte ein Windows-System seine Datensicherung per CIFS (aka Samba) auf einer Linux-basierten NAS. Das Konzept ist dabei schon etwas älter – die Windows-Software unterstützte bei der Einrichtung weder Kompression noch Deduplizierung, sodass hier das ZFS-Dateisystem der Linux-Kiste einiges an Platz einsparen konnte. Inzwischen ist die Windows-Software gewachsen: Kompression und Deduplizierung werden bereits vorab durchgeführt, dafür machten die vielen neuen Funktionen immer häufiger Probleme mit CIFS. Kaputte Locks, schlechte Performance, Verbindungsabbrüche – alles lässt sich recht genau auf die Kombination aus dem Server und CIFS zurückführen. Während eine „normale“ Kopie unter Linux mit etwa 100MB/s von statten geht schafft der Server nur 4MB/s. Andere Protokolle sind schneller, andere Windows-Server haben ebenfalls keine Probleme. Inzwischen sind ohnehin neue Platten fällig – Zeit hier gegenzusteuern.

Die Speicherung soll weiterhin auf der Linux-Kiste erfolgen – dort ist die Sicherung und Verwaltung deutlich zuverlässiger und flexibler. Andererseits habe ich keine Lust auf CIFS-Fehlersuche, also lassen wir es einfach weg – die Lösung: iSCSI. Der Windows-Server greift direkt auf den rohen Datenträger des Linux-Systems zu. Da wie erwähnt keine Linux-seitige Kompression stattfinden muss wird diese einfach per LVM verwaltet und ist über den Kernel-iSCSI-Server exportiert. Das Anlegen verläuft ohne Probleme, müssen nur noch die Daten rüben. Mit 4MB/s. Bei fast 4TB. Mit 5 Tagen Restzeit. Nope.

Also, fassen wir nochmal zusammen: Sowohl der alte als auch der neue Datenbestand liegen auf dem selben Linux-System. Warum nicht einfach da kopieren? NTFS-Schreiben unter Linux ist zwar nicht schnell, aber die 4MB/s-Marke sollte zu schaffen sein. Problem: Auf dem LVM-LV hat Windows automatisch eine GPT-Partitionstabelle angelegt, sie lässt sich also nicht direkt unter Linux mounten.

Um trotzdem an das NTFS-System zu kommen müssen wir erst mal wissen wo die passende Partiton beginnt. Hier kommt parted zum Einsatz, welcher auch GPT-Partitionstabellen unterstützt. Da wir die Angaben in Byte, nicht den üblichen Sektoren, benötigen muss die Anzeige erst ungeschaltet werden.

[root@nas ~]# parted /dev/speicher2/windows9
GNU Parted 3.2
/dev/dm-1 wird verwendet
Willkommen zu GNU Parted! Rufen Sie "help" auf, um eine Liste der verfügbaren Befehle zu erhalten.
(parted) unit B
(parted) print
Modell: Linux device-mapper (linear) (dm)
Festplatte  /dev/dm-1:  4178147540992B
Sektorgröße (logisch/physisch): 512B/512B
Partitionstabelle: gpt
Disk-Flags:

Nummer  Anfang      Ende            Größe           Dateisystem  Name                          Flags
 1      17408B      134235135B      134217728B                   Microsoft reserved partition  msftres
 2      135266304B  4178146492415B  4178011226112B  ntfs         Basic data partition          msftdata
(parted) quit

Wie wir sehen wurden auf dem LVM-LV durch Windows zwei Partitionen angelegt: Die Erste enthält Managementdaten, die Zweite ist unsere eigentliche NTFS-Datenpartition. Letztere beginnt bei 135266304 Byte – genau diesen Bereich müssen wir auf dem Datenträger also überspringen um auf das NTFS-Dateisystem zugreifen zu können. Also legen wir uns ein passendes Loop-Device an. Da ich bereits ein anderes Device aktiv habe nutze ich loop2 – generell ist die Zahl wählbar.

[root@nas ~]# losetup -o 135266304 /dev/loop2 /dev/speicher2/windows9
[root@nas ~]# mount -t ntfs-3g /dev/loop2 /mnt/test/
[root@nas ~]# mount | grep test
/dev/loop2 on /mnt/test type fuseblk (rw,nosuid,nodev,relatime,user_id=0,group_id=0,allow_other,blksize=4096)
[root@nas ~]# df -h test/
Dateisystem    Größe Benutzt Verf. Verw% Eingehängt auf
/dev/loop2      3,8T    604G  3,3T   16% /mnt/test

Passt doch, schon haben wir unter Linux nativen Zugriff auf das Device. Das Kopieren läuft nun mit 90MB/s – nicht ganz die bestmögliche Geschwindigkeit, für NTFS über fuse aber kein Schlechter wert – und etwas schneller als die 4MB/s der Windows-Kiste.

BTRFS-Recovery

Narf… Das war zu viel. Durch einen Umbau hatte sich offenbar ein Kabel im Lüfter meines Chipsatzes verheddert – keine gute Voraussetzung, wenn man mal eben Wine neu kompiliert. Es kommt, was kommen musste: Kernel panic.

Nunja, Fehler gefunden, weiter gehts. Nicht. Zwar startete das System, meine Home-Partition blieb aber verschwunden. Kurzer Blick auf den Aufbau: Mein Home liegt auf einer separaten Partition, ist mit LUKS verschlüsselt und nutzt – da ich die gigabyteweise IRC-Logs vorratsdatenspeichere und transparente Komprimierung wollte – BTRFS. Das Log verrät: LUKS selbst läuft, mount hingegen scheint sich aufzuhängen. In dmesg sieht alles OK aus, nur die normalen BTRFS-Meldungen, keine Fehler.

Strange, aber Reboot fixed ja fast alles, also schnell die magischen Zeichen eingetippt und zur Sicherheit im Rescue-Mode gestartet. Dort per Hand cryptsetup aufgerufen und erst mal btrfsck losgelassen. Kein Fehler. Mount? Nope.

OK, nun bin ich genervt, vor allem da die Kiste nicht unbedingt schnell bootet. Qemu to the rescue, also schnell ein Debian geklont und die Partition vorgesetzt. Schlechte Idee. Die bei Debian genutzten BTRFS-Libs/Module sind eine Nummer zu alt und können mit der Partition gar nichts anfangen. Ein Arch-Download später kann es weiter gehen.

Erst einmal ein normaler mount in der VM – vielleicht ist ja nur der Host kaputt, außerdem ist auf der CD ein älterer Kernel. Leider ohne erfolg, also VM-Reboot und den Hammer ausgepackt. Mit „mount -o recovery,nospace_cache“ lassen sich viele Fehler schon beheben, aber auch hier scheint der mount nichts zu vollziehen. Keine Reaktion, keine IO-Last, keine Fehlermeldung.

Die Lösung: btrfs_zero_log. Hiermit werden die offenen Transaktionen gelöscht. Die kann zwar zu Datenverlust von Änderungen, die kurz vor Absturz geschrieben wurden, führen, aber besser als gar keine Partition. Der mount in der VM war schlussendlich erfolgreich und auch der Host verfügte kurze Zeit später wieder über alle Dateien. Warum btrfsck das offenbar defekte Log nicht ankreidete ist mir allerdings ein Rätsel – sollte das nicht die Aufgabe des Tools sein?

Software als Windows-Service

Programme starten ist toll. Einige müssen aber immer wieder gestartet werden, hierzu nutzt man unter Windows so genannte „Dienste“. Leider sind das unter Windows NT (also auch z.B. Windows 7/8/10, Windows Server 2008/2012) keine einfachen Programme, sondern erfordern spezielle Registrierungen. Leider gent so etwas (soweit mir bekannt) nicht mit Hausmitteln.

Abhilfe schafft ein kleines Tool: winserv verwandelt ein beliebiges Programm in einen passenden Dienst. Hierbei gibt es folgende Modi:

install richtet ein Programm als Dienst ein
configure ändert einen vorhandenen Dienst
uninstall entfernt den Dienst

Zum Anlegen gibt man folgende Parameter:

-displayname Angezeigter Name des Dienstes
-description Beschreibung (das, was in der Diensteverwaltung in der zweiten Spalte steht)
-start Start-Art des Dienstes – „auto“ „demand“ oder „disabled“ (Bedeutung selbstredend, oder?)

Beispiel:

winserv install testdienst -displayname "Test-Dienst" -description "Test 123" -start auto c:\BLA.EXE

Alternativ kann man auch einen Geplanten Task mit dem Trigger „Bei Systemstart“ verwenden, hier muss man jedoch auf die komfortableren Prüf- und Verwaltungsfunktionen des Dienst-Managers verzichten.

Q’n’D Windows-Shutdown-Daemon in PHP

Alles in Deckung, ich mache wieder unschönes Zeugs. Ich hatte ja bereits erklärt wie man über RPC/Samba einen Windows-PC von Linux herunterfahren kann. Leider ist die Installation von Samba aus Embedded-Systemen eine eher ungünstige Sache und ist in meinem Fall wegen Speichermangel nicht drin. Allerdings ist sowohl auf dem Embedded-System als auch dem betroffenen Rechner PHP verfügbar. I aim to misbehave.

Auf dem herunterzufahrenden Windows-Rechner wird per PHP ein TCP-Socket geöffnet. Dieser Code basiert auf einem Beispiel von Michael Kliewe. Um Scriptkiddies nicht direkt Zugang zu geben ist etwas (sehr schlechte) Challenge-Response-Authentifizierung drin – nunja, ist kein kritisches System. Wird der Client bestätigt folgt ein simples Shutdown per exec. Nicht viel, aber schnell Fertig und funktioniert:

<?php
class SocketChatServer {
    private $address = '0.0.0.0';   // 0.0.0.0 means all available interfaces
    private $port = 12345;          // the TCP port that should be used
    private $maxClients = 10;
 
    private $clients;
    private $socket;
    
    private $salt = 'YourSalt';
    private $pass = 'YourSecret';
 
    public function __construct() {
        // Set time limit to indefinite execution
        set_time_limit(0);
        error_reporting(E_ALL ^ E_NOTICE);
    }
 
    public function start() {
        // Create a TCP Stream socket
        $this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        // Bind the socket to an address/port
        socket_set_option($this->socket, SOL_SOCKET, SO_REUSEADDR, 1);
        socket_bind($this->socket, $this->address, $this->port);
        // Start listening for connections
        socket_listen($this->socket, $this->maxClients);
 
 
        $this->clients = array('0' => array('socket' => $this->socket));
 
        while (true) {
            // Setup clients listen socket for reading
            $read[0] = $this->socket;
            for($i=1; $i<count ($this->clients)+1; ++$i) {
                if($this->clients[$i] != NULL) {
                    $read[$i+1] = $this->clients[$i]['socket'];
                }
            }
 
            // Set up a blocking call to socket_select()
            $ready = socket_select($read, $write = NULL, $except = NULL, $tv_sec = NULL);
 
            /* if a new connection is being made add it to the client array */
            if(in_array($this->socket, $read)) {
                for($i=1; $i < $this->maxClients+1; ++$i) {
                    if(!isset($this->clients[$i])) {
                        $this->clients[$i]['socket'] = socket_accept($this->socket);
                        socket_getpeername($this->clients[$i]['socket'], $ip);
                        $this->clients[$i]['ipaddy'] = $ip;
 
                        socket_write($this->clients[$i]['socket'], 'Welcome to the Shutdown Control System'."\r\n");
                        socket_write($this->clients[$i]['socket'], 'Your personal code is '.md5($this->salt.strftime('%Y-%m-%d').$ip)."\r\n");
 
                        $this->log("New client #$i connected: " . $this->clients[$i]['ipaddy']);
                        break;
                    } elseif($i == $this->maxClients - 1) {
                        $this->log('Too many Clients connected!');
                    }
 
                    if($ready < 1) {
                        continue;
                    }
                }
            }
 
            // If a client is trying to write - handle it now
            for($i=1; $i<$this->maxClients+1; ++$i) {
                if(in_array($this->clients[$i]['socket'], $read)) {
                    $data = @socket_read($this->clients[$i]['socket'], 1024, PHP_NORMAL_READ);
 
                    if($data === FALSE) {
                        unset($this->clients[$i]);
                        $this->log('Client disconnected!');
                        continue;
                    }
 
                    $data = trim($data);
 
                    if(!empty($data)) {
                        switch ($data) {
                            case 'exit':
                            case 'quit':
                                socket_write($this->clients[$i]['socket'], "Disconnecting without any action, Goodbye.\r\n");
                                $this->log("Client #$i is exiting");
                                unset($this->clients[$i]);
                                continue;
                            case 'shutdown-'.md5($this->pass.md5($this->salt.strftime('%Y-%m-%d').$ip)):
                                // first write a message to all connected clients
                                for($j=1; $j < $this->maxClients+1; ++$j) {
                                    if(isset($this->clients[$j]['socket'])) {
                                        if($this->clients[$j]['socket'] != $this->socket) {
                                            socket_write($this->clients[$j]['socket'], "System will be shut down now...\r\n");
                                        }
                                    }
                                }
                                // Close the master sockets, server termination requested
                                exec('shutdown /s /t 15 /c "System wurde per Fernbedienung ausgeschaltet"');
                                $this->log("Terminated server (requested by client #$i)");
                                exit;
                            case 'whoami':
                                // first write a message to all connected clients
                                socket_write($this->clients[$i]['socket'], "You are registred with the source IP ".$this->clients[$i]['ipaddy']." - your Code was ".md5($this->salt.strftime('%Y-%m-%d').$ip)." \r\n");
                                
                                break(2);
                            default:
                                for($j=1; $j < $this->maxClients+1; ++$j) {
                                    if(isset($this->clients[$j]['socket'])) {
                                        if(($this->clients[$j]['socket'] != $this->socket)) {
                                            $this->log($this->clients[$i]['ipaddy'] . ' is sending a message to ' . $this->clients[$j]['ipaddy'] . '!');
                                            socket_write($this->clients[$j]['socket'], '[' . $this->clients[$i]['ipaddy'] . '] says: ' . $data . "\r\n");
                                        }
                                    }
                                }
                                break(2);
                        }
                    }
                }
            }
        } // end while
    }
 
    private function log($msg) {
        // instead of echoing to console we could write this to a database or a textfile
        echo "[".date('Y-m-d H:i:s')."] " . $msg . "\r\n";
    }
}

$srv = new SocketChatServer;
$srv->start();
?>

Der Client bastelt sich eine passende Authentifizierung und spielt Zündknopf:

function pc_shutdown() {                                                                                                                                                                                                              
                $pass = 'YoutSecret';                                                                                                                                                                                                         
                                                                                                                                                                                                                                              
                $fp = fsockopen('pc.name', 12345, $errno, $errstr, 2);                                                                                                                                                                              
                if(!$fp) return false;                                                                                                                                                                                                        
                                                                                                                                                                                                                                              
                $line = fgets($fp); //Greeting                                                                                                                                                                                                
                $line = fgets($fp); //Hash                                                                                                                                                                                                    
                                                                                                                                                                                                                                              
                preg_match('/code is ([\w\d]{32})/', $line, $match);                                                                                                                                                                          
                $seed = $match[1];                                                                                                                                                                                                            
                                                                                                                                                                                                                                              
                $cmd = 'shutdown-'.md5($pass.$seed)."\n";                                                                                                                                                                                     
                                                                                                                                                                                                                                              
                fwrite($fp, $cmd);                                                                                                                                                                                                            
                                                                                                                                                                                                                                              
                var_dump(fgets($fp));                                                                                                                                                                                                         
                                                                                                                                                                                                                                              
                fclose($fp);                                                                                                                                                                                                                  
        }

Hoffen wir, dass es läuft und ich nie wieder drauf schauen muss, denn irgendwo tut sowas selbst mir weh 😉

Symantec Backup Exec: Bandstatus per PowerShell auslesen

Symantec Backup Exec ist eine in Windows-Umgebungen recht verbreitete Backup-Software. Seit einigen Versionen lassen sich große Teile auch über die „Microsoft-Bash“ PowerShell steuern. Für meinen Zweck wollte ich eine Liste aller im angeschlossenen Bandwechseler eingelegten Bänder und deren Status, so kann ich feststellen welche entnommen werden sollen. Im ersten Schritt muss das PowerShell-Modul geladen werden:

Import-Module 'C:\Program Files\Symantec\Backup Exec\Modules\BEMCLI\BEMCLI'

Nun wird die Liste der Bännder im Wechsler ausgelesen – hier lässt sich feststellen welches Band in welchem Slot des Wechslers verfügbar ist:

Get-BERoboticLibrarySlot -RoboticLibraryDevice "TapeLib01"

Name       SlotNumber IsCleaningSlot  Media
----       ---------- --------------  -----
Schacht 1  1          False           ADLR03L5
Schacht 2  2          False           ADLR05L5
Schacht 3  3          False           ADLR11L5
Schacht 4  4          False           ADLR13L5
Schacht 5  5          False           ADLR24L5
Schacht 6  6          False           ADLR31L5
Schacht 7  7          False           ADLR33L5
Schacht 8  8          False           ADLR48L5
Schacht 9  9          False           ADLR34L5
Schacht 10 10         False           ADLR41L5
Schacht 11 11         False           ADLR49L5
Schacht 12 12         False           ADLR60L5

Zuletzt werden die zugehörigen Banddaten wie z.B. die Dauer des Software-Schreibschutzes gelesen:

Get-BEMedia -MediaVault "Online-Bandmedien" -Verbose | Format-List Name,MediaSet,OverwriteProtectedUntilDate,OverwriteProtectedUntilDate -Force

Name                        : ADLR03L5
MediaSet                    : Monatssicherungen (12 Monate schreibschutz)
OverwriteProtectedUntilDate : 06.03.2016 02:39:53
[…]

Die Daten werden in meinem Fall am Ende einer externen Schnittstelle übergeben, welche die Bandstati sortiert und entsprechende Warnmeldungen zur Entnahme generieren kann.

FTP-Uploads per Shell-Script

Ab und an komme auch ich nicht drumrum mit Zielen zu arbeiten, welche keine SSH/SFTP-Verbindung zulassen, sondern nur per FTP(S) erreichbar sind. Grade beim Automatisieren über Shell-Scripte ist das reichlich unschön. Ein praktischer Client ist in diesem Fall das Urgestein ncftp. Mit dessen Tools lässt sich z.B. schnell ein ein entferntes Verzeichnis löschen und durch die lokale Kopie ersetzen:

echo 'rm foo/bar/*
rm foo/baz/*
rmdir foo/bar
rmdir foo/baz
' | ncftp -u $USER -p $PASS $HOST

ncftpput -R -u $USER -p $PASS $HOST /foo/* ~/dev/foo/*

Windows Shutdown per Linux

Ab und an möchte man entfernte Rechner mal runterfahren. Mit Linux-Zielen ist das per ssh üblicherweise kein Problem, möchte man jedoch von einem Linux-PC den Shutdown-Befehl an einen Windows-Rechner geben muss man schon einmal suchen. Abhilfe schafft wie üblich Samba, welches den „net“-Befehl mitbringt. Ein Shutdown sieht dann wie folgt aus:

net rpc SHUTDOWN -C "Grund für den Shutdown" -f -I 127.0.0.1 -U username%password