PHP 7.x auf Windows Server 2016 mit IIS installieren, Schritt für Schritt

Installieren wir ein aktuelles PHP (7.2 in diesem Fall) auf einem Windows Server 2016 in 64bit. Da wir den IIS nutzen und ein lokales CGI-Script-Handling einrichten wollen, nutzen wir die NTS (Non Thread Safe) Variante.

Auf die Unterschiede zwischen „Thread Safe“ und „Non Thread Safe“ gehen wir hier nich genauer ein. Schnelle Admins wissen aber:

  • Apache + LoadModule: Thread Safe
  • Apache + FastCGI: Non-Thread Safe
  • IIS: Thread Safe
  • IIS + FastCGI: Non-Thread Safe « Diese Anleitung

Installation von PHP 7.2 auf Windows Serrver 2016 (IIS)

  1. Windows Server 2016 installieren+updaten, IIS und Tools hinzufügen. Die Installation dauert einen Moment. Der Telnet-Client ist nicht zwingend notwendig, aber oft hilfreich.
    PS C:\> Import-Module servermanager
    PS C:\> Install-WindowsFeature -name web-server,web-cgi –IncludeManagementTools
    PS C:\> Add-WindowsFeature telnet-client
  2. PHP herunterladen und installieren: https://windows.php.net/download/. „VC15 x86 Non Thread Safe„. Wir empfehlen 32bit (x86) wegen der Extensions, es gibt noch nicht alle Extensions in x64. Jetzt grade aktuell war PHP in der Version 7.2.9.
  3. Visual C++ 2015 Runtime Update 3 RC (oder auch gleich 2017) in x86 und x64 herunterladen und installieren: https://www.microsoft.com/DE-de/download/details.aspx?id=52685
  4. Die PHP ZIP-Datei  (als Administrator) entpacken (z.B. „%Program Files (x86)%\PHP“)
  5. Kopieren der „php.ini-development“ in die „php.ini“
    PS C:\Program Files (x86)\php-nts-x86> Copy-Item .\php.ini-development .\php.ini2
  6. PHP.ini bearbeiten
    error_log = C:\inetpub\logs\php_errors.log
    max_execution_time = 60
    max_input_time = 90
    memory_limit = 256M
    default_charset = "UTF-8"
    upload_tmp_dir = "C:\inetpub\temp\IIS Temporary Compressed Files"
    upload_max_filesize = 16M
    allow_url_fopen = Off
    extension=php_wincache.dll
  7. Den PHP Interpreter zur System-PATH-Variable hinzufügen
    1. Systemeigenschaften > Erweitert > Umgebungsvariablen > Systemvariablen > Eintrag „Path“ bearbeiten > Neu > <PFAD ZU PHP> einfügen > OK > OK
  8. „Wincache Extensian for PHP“ 2.0 in 64bit herunterladen: https://www.iis.net/downloads/microsoft/wincache-extension (Aktuell: „wincache-2.0.0.8-dev-7.1-nts-vc14-x64.exe“) und in den PHP-Pfad nach \ext entpacken
  9. PHP im IIS konfigurieren
    1. „Internetinformationsdienste (IIS)-Manager“ starten > Links den Server auswählen (oberste Ebene) > „Handlerzuordnungen“ öffnen
    2. „Modulzuordnung hinzufügen“:
      1. Anforderungspfad: *.php
      2. Modul: FastCgiModule
      3. Ausführbare Datei: „C:\Program Files (x86)\<PHP-PFAD>\php-cgi.exe“
      4. Name: PHP
      5. Einschränkungen: „Handler nur bei folgender Zuordnung aufrufen“ auf „Datei oder Ordner“ stellen
  10. Standartdokument(e) hinzufügen
    1. Internetinformationsdienste (IIS)-Manager“ starten > Links den Server auswählen (oberste Ebene) >Standdartdokument
    2. Hinzufügen > „index.php“
  11. Schon fertig 🙂

Installation von Microsoft SQL Server Treibern für PHP unter Windows/IIS

  1. Download der „Microsoft PHP drivers Version for SQL Server“ (aktuell 7.2): https://github.com/Microsoft/msphpsql/releases
  2. Entpacken von x86\php_pdo*.dll nach <PHPPFAD>\ext
  3. Bearbeiten der PHP.ini
    extension=php_sqlsrv_72_nts.dll
  4. Download und Installation der „Microsoft® ODBC Driver 17 for SQL Server“ in 64bit: https://www.microsoft.com/de-DE/download/details.aspx?id=56567
  5. Webserver neustart mit „IISRESET“
  6. Fertig 🙂

Ob das jeweilige Modul geladen werden konnte, lässt sich an der Kommandozeile mit „php -m“ recht gut überprüfen.

Testen der Installation von PHP auf IIS

In C:\inetpub\wwwroot eine Datei „phpinfo.php“ anlegen mit dem folgenden Inhalt:

<?php
    phpinfo();
?>

Und aufrufen von http://<SERVERNAME>/phpinfo.php

 

In Office 365 mit der Powershell die Benutzerkontaktdaten wie Straße oder Ort Massenhaft ändern

Problem

Es sollen viele oder gleich alle Office 365 Benutzer geändert werden. Wegen eines Umzuges stimmt der Ort nicht mehr, wegen eines verdammten CSV-Ascii-Importfehlers stimmen Sonderzeichen nicht oder es hat sich eine andere Eigenschaft bei vielen Benutzern geändert die nun auf einmal angepasst werden soll.

Lösung

Zuerst muss man sich mit der „Windows Azure Active Directory-Modul für Windows PowerShell“ Powershell mit dem Office365 verbinden:

PS C:\> Connect-MsolService
    • Eigenschaften aller Benutzer sofort ändern (hier: ‚Straße‘)
      PS C:\> Get-MsolUser | Set-MsolUser -Street "Neue Strasse 815"
    • Eigenschaften der Benutzer ändern, die noch die alte Straße eingetragen haben
      PS C:\> Get-MsolUser | ? { $_.StreetAddress -eq 'Alte Adresse' } | Set-MsolUser -StreetAddress 'Neue Adresse'
    • Eigenschaften von nur zwei Benutzern ändern
      PS C:\> Get-MsolUser | ? { $_.UserPrincipalName -eq '[email protected]' -Or $_.UserPrincipalName -eq '[email protected]' } | Set-MsolUser

Active Directory: Wann hat sich ein Benutzer zuletzt angemeldet?

Problem

Wann hat sich ein Benutzer oder Konto zuletzt am Active Directory angemeldet? Die Objekt-Registerkarte im ActiveDirectory Benutzer- und Computer SnapIn ist da nicht sondelrich auskunftsfreudig.

Die Objekteigenschaft „LastLogon“ lässt sich zwar an der PowerShell mittels „Get-ADUser“ auslesen, aber nur als Large-Integer, der die Anzahl von 100-Nanosekunden-Intervallen seit dem 1.1.601 in UTC anzeigt. Leicht esoterischer Wert …

Lösung

Dieses PowerShell-Script wirft den Wert lesbar raus und funktioniert auch außerhalb von Domänencontrollern (RSAT-Tools vorausgesetzt):

Import-Module activedirectory
([DateTime][long](
     $(ForEach ($dc in ((Get-ADDomaincontroller -filter *).name)) 
        {
           (Get-ADUser -Identity "administrator" -Properties "LastLogon" -server $dc).LastLogon
        }
 ) | Measure -Maximum).Maximum).AddYears(1600)

Oder für besonders faule Admins auch als Einzeiler:

([DateTime][long]($(ForEach($dc in ((Get-ADDomaincontroller -filter *).name)){(Get-ADUser -Identity "mroelz" -Properties "LastLogon" -server $dc).LastLogon})|Measure -Maximum).Maximum).AddYears(1600)

Powershell „Für jede Zeile in einer Textdatei“ … foreach Powershell Schnippsel

Weil ich JEDESMAL diesen blöden Syntax nachschaue, hier mein persönlichliches Powershell foreach-Bookmark:

[PS] C:\> foreach ( $eintrag in Get-Content .\liste.txt) { Mach-Irgendwas $eintrag }

Zum Beispiel:

[PS] C:\> foreach ( $foo in Get-Content .\liste.txt ) { Write-Host $foo }

Alternativ:

Get-Content .\liste.txt | foreach { $_ }

Ich weiss nicht warum, das bleibt einfach nicht in meinem Kopf haften. Das gute alte „for %%i in …“ hat aber auch eine ganze Weile gedauert, zugegeben.

Es gibt in der PowerShell zwei verschieden Varianten von ForEach:

  • Das ForEach-Object { … } Cmdlet
  • Die  ForEach() { … } Schleife

Beide Arten von ForEach können eingesetzt  werdenum, für jedes einzelne Objekt aus einer Menge von Objekten, etwas ausführen zu können.

  • ForEach-Object ist ein Cmdlet und wird in der Pipeline eingesetzt
  • Die ForEach() Schleife wird nicht innerhalb der Pipeline eingesetzt.

Mehr Input und Beispiele gibt es beim Peter Kriegel.

Veraltete Computerkonten im Active Directory finden

Problem

Eine wiederkehrende und frustrierende Verwaltungsaufgabe für das Active Directory ist, alte Computerkonten (Server, Desktop-PCs, Laptops … ) sauber zu entfernen. Viele Admins fügen eigentlich immer nur hinzu, alte Konten werden nicht aufgeräumt. Einen eingebauten Automatismus dafür gibt es nicht.

Ein Blick auf die Registerkarte „Objekt“ eines Computerkontos zeigt zwar, wann die Update-Sequenznummer (USN) aktualisiert wurde, aber nicht wann sich der Computer das letzte mal bei der Domäne angemeldet hat.

Lösung

Es gibt verschiedene Möglichkeiten, um festzustellen, ob ein Computerkonto in Active Directory veraltet ist. Der empfohlene („Best Practice“) Ansatz besteht darin, eine Richtlinie für Ihre Active Directory-Domäne einzurichten, in der die Regeln erläutert werden. Das Problem dabei sind aber remote-Systeme, wie zum Beispiel ein Laptop, wo der entsprechende Benutzer in der Lage ist, alles zu tun, was er über eine Webanwendung benötigt.

Inaktive Computer im AD mit dsquery suchen

C:\> dsquery computer -inactive <WOCHEN>

Der Befehl wird so für die gesamte Domäne (des ausführenden Computers) ausgeführt. Einschränkungen sind aber möglich:

C:\> dsquery computer OU=Hiersuchen,DC=domain,DC=local -inactive <WOCHEN>

Leider kann dsmove nicht mit dieser Liste direkt gepiped werden, da ist die Powershell etwas komfortabler. Um also ältere Computer in eine eigene OU zu verschieben, ist an der CMD-Shell ein Dreizeiler erforderlich:

dsquery computer -inactive <WOCHEN> > liste.txt
FOR /f %%i in (liste.txt) do dsmove %%i -newparent OU=<INACTIVE-OU>,DC=domain,DC=local
del liste.txt

 

 

Inaktive Computer im AD mit der PowerShell suchen

Das geht sogar in Tagen, nicht nur in Wochen. Dafür muss die Variable entsprechend geändert werden (-60).

PS C:\> $then = (Get-Date).AddDays(-60)
PS C:\> Get-ADComputer -Property Name,lastLogonDate -Filter {lastLogonDate -lt $then}

Die ausgegebenen Objekte lassen sich so direkt weiterpipen.

Mehr Beispiele an der Powershell

# Ausgabe veralteter Computerkonten als halbwegs sinnvolle Liste
PS C:\> Get-ADComputer -Property Name,lastLogonDate -Filter {lastLogonDate -lt $then} | Sort-Object -Property "lastLogonDate" | FT Name,lastLogonDate
# Veraltete Computerkonten im AD deaktivieren
PS C:\> Get-ADComputer -Property Name,lastLogonDate -Filter {lastLogonDate -lt $then} | Set-ADComputer -Enabled $false
# Veraltete Computerkonten im AD löschen
PS C:\> Get-ADComputer -Property Name,lastLogonDate -Filter {lastLogonDate -lt $then} | Remove-ADComputer

 

Ein neues VLAN über den vCenter-Server zu einem oder allen ESXi-Hosts im Cluster hinzufügen

Man fügt ja eine neu getaggte VLAN Portgruppen zur Segementierung auf jedem ESXi-Host einzeln zum vSwitch hinzu, es sei denn man verfügt üben den zentralisierten NSX/Distributed-Luxus. Oder macht gleich SDN überall 🙂

Der Vorgang an sich kann je nach Clustergröße etwas dauern und zudem sehr ermüdent sein. Das folgende PowerCLI-Script vereinfacht diese Arbeit deutlich und erledigt den Job in wenigen Sekunden.

„Stelle ein neues VLAN unserer Switches am bestehenden vSwitch ALLER Hosts zur Verfügung“

PowerCLI C:\> Connect-VIServer vcenter01.localnetwork.local
PowerCLI C:\> get-cluster -name MEINSEXYCLUSTER | Get-VMHost | Get-VirtualSwitch -name "vSwitch1" | New-VirtualPortGroup -Name "NEUES_SEXY_SEGMENT_LAN33" -VLanId "1607"

„Stelle ein neues VLAN unserer Switches am bestehenden vSwitch an EINEM Hosts zur Verfügung“

PowerCLI C:\> Connect-VIServer vcenter01.localnetwork.local
PowerCLI C:\> get-cluster -name MEINSEXYCLUSTER | Get-VMHost SEXYHOSTNAME | Get-VirtualSwitch -name "vSwitch1" | New-VirtualPortGroup -Name "NEUES_SEXY_SEGMENT_LAN33" -VLanId "1607"

„Entferne ein VLAN an den bestehenden vSwitches ALLER Hosts“

PowerCLI C:\> Connect-VIServer vcenter01.localnetwork.local
PowerCLI C:\> get-cluster -name "MEINSEXYCLUSTER " | Get-VMHost | Get-VirtualSwitch -name "vSwitch1" | Get-VirtualPortGroup -Name "NEUES_SEXY_SEGMENT_LAN33" | Remove-VirtualPortGrou

PowerCLI rockt einfach. Mehr zum Thema:

Ressourcenpostfach Kalenderbuchungen automatisch akzeptieren um Konflikte zu vermeiden

Problem:

Ein Ressourcenpostfach (Gerätepostfach) soll Kalenderbuchungen automatisch akzeptieren. In der Standardeinstellung sind Konflikte bei der Buchung möglich.

Lösung:

Standardmäßig werden bei Gerätepostfächern Kalenderbuchungen zwar als „Mit Vorbehalt“ im Kalender eingetragen, allerdings nicht automatisch bestätigt. Somit sind auch doppelte Buchungen möglich.

Diese Einstellung lässt sich relativ schnell via Exchange-Management-Shell ändern:

Set-CalendarProcessing -Identity "POSTFACH" -AutomateProcessing AutoAccept