レジストリのキーが存在するかどうかチェック

レジストリのキーが存在するかどうかチェックするPowershell

$tmp1 = test-path HKLM:"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{4A0E73BB-0D67-4DB7-87BE-751068774920}"
$tmp2 = test-path HKLM:"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{4A0E73BB-0D67-4DB7-87BE-751068774920}"
If (($tmp1 -eq $false) -and ($tmp2 -eq $false)){ Write-Output "Not Found." }

SCCMでディスクを自動クリーンアップ

SCCMを使っていると、いろいろなことをやってみたくなります。
今回は、SCCMを使ってディスクを自動クリーンアップすることにします。

ただし、普通にパッケージを展開しても芸がありません。
ミソは、C:ドライブの空き容量を定期的にチェックし、一定の容量を下回った場合に自動クリーンアップされるようにする、というものです。

アプリケーションの作成

  1. まず、自動クリーンアップするためのアプリケーションを作成します。ここでパッケージではなくアプリケーションを使用する理由は後述します。

    1. 今回は、2つのスクリプトを用意しました。
      1つにまとめても良いのですが、もともと、こちらの情報を参考にcleanmgr.exe を自動実行するPowershellスクリプトを作成し、これに加えてテンポラリディレクトリ、SCCMのキャッシュフォルダのクリアもしたかったため、このような構成になりました。単に手抜きです。

      [参考] Greg's Systems Management Blog - Automating the Disk Cleanup Utility
      https://gregramsey.net/2014/05/14/automating-the-disk-cleanup-utility/

      こちらのバッチファイルで、テンポラリディレクトリのクリア、別のPowershellスクリプトの呼び出しを行います。

      auto_cleanmgr.bat

      powershell.exe -command Set-ExecutionPolicy Unrestricted
      del /Q c:\windows\temp\*.*
      powershell.exe -command \\m-mgmt-sccm01\smspkgg$\scripts\auto_cleanmgr.ps1
      exit 0
      こちらPowershellスクリプトで、SCCMキャッシュのクリア、cleanmgr.exeの自動実行を行います。

      auto_cleanmgr.ps1

      ######################################################### Capture current free disk space on Drive C

      $FreespaceBefore = (Get-WmiObject win32_logicaldisk -filter "DeviceID='C:'" | select Freespace).FreeSpace/1GB

      ######################################################### Clear ccmcache of SCCM client

      $resman = New-Object -ComObject "UIResource.UIResourceMgr"
      $cacheInfo = $resman.GetCacheInfo()
      "clearing ccmcache. . ."
      $cacheInfo.GetCacheElements() | ForEach{ $cacheInfo.DeleteCacheElement($_.CacheElementID) }

      ######################################################### CleanMgr.exe Automation
      #
      #http://gregramsey.net
      #more info here:
      #http://support.microsoft.com/kb/253597

      #ensure we're running on windows 8.1 first
      #if ((Get-CimInstance win32_operatingsystem).version -eq '6.3.9600') {

      #Set StateFlags0012 setting for each item in Windows 8.1 disk cleanup utility
      if (-not (get-itemproperty -path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Active Setup Temp Folders' -name StateFlags0012 -ErrorAction SilentlyContinue)) {
      set-itemproperty -path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Active Setup Temp Folders' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\BranchCache' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Downloaded Program Files' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Internet Cache Files' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Memory Dump Files' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Old ChkDsk Files' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Previous Installations' -name StateFlags0012 -type DWORD -Value 2
      # set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Recycle Bin' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Service Pack Cleanup' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Setup Log Files' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\System error memory dump files' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\System error minidump files' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Temporary Files' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Temporary Setup Files' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Thumbnail Cache' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Update Cleanup' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Upgrade Discarded Files' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\User file versions' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Windows Defender' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Windows Error Reporting Archive Files' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Windows Error Reporting Queue Files' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Windows Error Reporting System Archive Files' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Windows Error Reporting System Queue Files' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Windows ESD installation files' -name StateFlags0012 -type DWORD -Value 2
      set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Windows Upgrade Log Files' -name StateFlags0012 -type DWORD -Value 2
      }

      cleanmgr /sagerun:12

      do {
      "waiting for cleanmgr to complete. . ."
      start-sleep 15
      } while ((get-wmiobject win32_process | where-object {$_.processname -eq 'cleanmgr.exe'} | measure).count)

      $FreespaceAfter = (Get-WmiObject win32_logicaldisk -filter "DeviceID='C:'" | select Freespace).FreeSpace/1GB

      "Free Space Before: {0}" -f $FreespaceBefore
      "Free Space After: {0}" -f $FreespaceAfter

      #}

    2. 通常通り、auto_cleanmgr.batを実行するアプリケーションを作成します。

      ここで1つ仕掛けをします。
      アプリケーションの展開の種類で、下記のような検出方法を設定します。

      • 「カスタムスクリプトを使用してこの展開の種類のプレゼンスを検出する」を選択
      • スクリプトの種類」はVBScriptを選択して、下記のようなスクリプトを設定
        set fsobj = CreateObject("Scripting.FileSystemObject")
        set d1 = fsobj.GetDrive("C")
        If d1.FreeSpace/1024/1024>10024 Then
        WScript.StdOut.WriteLine d1.FreeSpace/1024/1024
        End If
        WScript.Quit(0)
      検出方法のスクリプトでは、スクリプトの出力がなにかあった場合、正常に検出されたことになります。逆に、何も出力が無いと、アプリケーションは未検出となり、インストールを実行しようとします。これを利用して、スクリプトでディスクの空き容量をチェックし、一定容量(このスクリプトでは約1GB)を上回った場合だけメッセージを出力するようにしておきます。このことで、検出の結果、アプリケーションが未検出と認識されて、スクリプトが実行されます。
      これが、パッケージではなくアプリケーションを使用した理由です。

    3. あとは、通常通りこのアプリケーションを展開するだけです。
以上の方法で実際に動作させることができますが、これとは別にディスクの空き容量が少ないPCだけを選択するデバイスコレクションを作成しました。このコレクションに展開設定をしておけば、実行が不要なデバイスにも展開する必要がなくなります。

コレクションの作成

方法は下記のとおりです。
  1. あらかじめ、ハードウェアインベントリのなかでディスクの空き容量を取得するよう、クライアント設定を変更します。これは、デフォルトではハードウェアインベントリでディスクの空き容量は取得する設定になっていないためです。

    1. 適用されているクライアント設定のダイアログで、ハードウェアインベントリ - ハードウェアインベントリクラスの「クラスの設定」ボタンをクリックします
    2. ツリーの中にある、論理ディスク - 空き容量(MB)のチェックを入れます

  2. バイスコレクションの作成の際、メンバシップ規則に、下記のようなクエリを設定します。
    select * from SMS_R_System full join SMS_G_System_LOGICAL_DISK as LDISK on LDISK.ResourceID = SMS_R_System.ResourceId where LDISK.FreeSpace <= 1024 and LDISK.DeviceID = "C:"
    この例では、C:ドライブの空き容量が1GBを下回ったデバイスのみがデバイスコレクションのメンバーになります。

SCCMによるIE11のデプロイ

さて、SCCMによるIE11のデプロイですが、いきなり問題があります。
必要な更新をインストール後、IE11のインストール後、IE11の更新のインストール後、それぞれの少なくとも3回、PCを再起動する必要があるのです。単純なパッケージを使用したバックグラウンドでのインストールではなく、再起動が行えるタイミングでユーザーにインストールを開始してもらう操作が必要になります。

このため、タスクシーケンスを利用します。
作成方法は下記のとおりです。

  1. 新しくタスクシーケンスを作成します。

  2. まず、IE11が既にインストールされているかどうか確認するステップです。
    こちらのようなWMIクエリを条件に指定し、グループを作成します。この条件がFALSEの場合、IE11のインストールへ進みます。
    SELECT * FROM Win32_QuickFixEngineering WHERE HotFixID = "KB2841134"

  3. 32ビットか64ビットを判定し、グループを分けます。

  4. 前提となる更新をインストールします。
    こちらのようなステップを作成していきます。

    このとき、オプションで条件を指定しておくと、既にインストール済みの場合はスキップするため時間を短縮できます。

    SELECT * FROM Win32_QuickFixEngineering WHERE HotFixID = "KB2533623"

  5. これは私の試行錯誤の結果ですが、/norestart で全て一気にインストールすると、正常にインストールできない場合があるらしく、再起動の回数が増えますが、KB2729094についてはインストール後一旦再起動しておいたほうがよさそうです。

    このため、KB2729094については、別にグループを作成し、インストールした場合は一旦再起動するようにしました。

    1. まず上記と同様の方法でKB2729094がインストールされているかどうか確認し、結果を変数に設定します。

    2. KB2729094のグループを作成し、変数によって実行するかどうか判定します。

  6. いよいよIE11のインストールですが、このまえに下記のようなスクリプトを実行します。
    On Error Resume Next 
    strComputer = "."
    SET objWMIService = GETOBJECT("winmgmts:\\" & strComputer & "\root\cimv2")
    SET colItems = objWMIService.ExecQuery("Select HotFixID from Win32_QuickFixEngineering where HotFixID='KB2729094'")

    FOR EACH objItem in colItems
    Wscript.Echo objItem.HotFixID
    NEXT

    WSCRIPT.ECHO "DONE!"
    WSCRIPT.QUIT
    これにより、一度WMIクエリを実行しておき、結果をキャッシュさせ、IE11のインストーラ内でのWMIクエリの実行時間を短縮するのが狙いです。

  7. IE11をインストールします。

  8. 引き続き、IE11に必要な更新をインストールします。

    ここで1点注意があります。

    IE11でエンタープライズモードを使用するには KB2929437 が必要ですが、IE11がインストールされる前にこのアップデートを手動でインストールした場合や、IE11を一旦アンインストールしてしまった場合、IE11をインストール後再度インストールする必要があります。ところがこの状態でも、WMIクエリではインストール済みとして結果が返ってきてしまいます。

    このため、当初はWMIクエリによりチェックして、インストールされていない場合だけ実行するようにしていたのですが、この条件をはずしIE11をインストール後無条件に実行するようにしています。

これで、IE11をインストールするひととおりのタスクシーケンスが出来ました。あとは、これを「利用可能」としてデプロイし、ユーザーに実行してもらうだけです。
もちろん、「必須」でデプロイしてバックグラウンドで実行しても構いません。

IE11のインストールに失敗する

IE11のインストールには、必要となる前提条件やインストーラ自体にも問題があり、ネット上でも多数の問合せが見つかり、IT管理者は大変苦労されているようです。

私もSCCMを使用したIE11のデプロイに苦労しましたので、覚え書きしておきます。ただしこの方法でも100%成功するかどうかは微妙です。

  1. インストールに必要な更新

    まず前提として必要となるアップデートをあらかじめインストールする必要があります。必要な更新は、こちらのKBにまとめられています。

    Internet Explorer 11 用必須更新プログラム
    https://support.microsoft.com/ja-jp/kb/2847882

  2. IE11のインストール

    IE11のインストール時、インストーラは必要な更新がインストールされているか確認します。ところが困ったことに、この確認で使用するWMIクエリがタイムアウトし、結果的にインストールが失敗することがあります。

    IE11インストールログ c:\windows\IE11_main.log を確認すると、決まってこちらのようなエラーが出ています。

    WMI query for Hotfixes timed out. Query string: 'Select HotFixID from Win32_QuickFixEngineering WHERE HotFixID="KB2729094"'  Error: 0x00040004 (262148).
    KB2729094 がインストールされているかどうか確認するWMIクエリがタイムアウトしています。

    こちらのブログやフォーラム等の情報によると、IE11インストーラのWMIクエリのタイムアウトは10秒しかなく、KB2729094 を確認するWMIクエリに20秒以上掛かる場合があることから、タイムアウトしてしまうようです。

    (参考) IE11 インストール失敗への対処方法 (2)
    http://blogs.technet.com/b/jpieblog/archive/2015/12/14/3658212.aspx

  3. IE11に必要な更新

    IE11には、互換性を維持するために新たにエンタープライズモードという機能が追加されています。ただし、この機能を利用するには、IE11にさらに KB2929437 の更新をインストールする必要があります。

    Windows 7 および Windows Server 2008 R2Internet Explorer 11 のセキュリティ更新プログラムについて (2014 年 4 月 8 日)
    https://support.microsoft.com/ja-jp/kb/2929437

以上を踏まえての、SCCMによるIE11のデプロイについては、別の記事にまとめます。
http://d.hatena.ne.jp/hmunakata/20160106/1452043955

EMC VNXの情報をCacti用に取得するスクリプト

#!/bin/bash
#
# Created: 2014/12/03 Hiroshi Munakata
# Updated: 2014/12/08
#
# vnx_sysstat.sh [Target IP] [Server Name]
#

TMP=/tmp/vnx_expect_$$.log
TMP2=/tmp/vnx_expect_2_$$.log
TMP3=/tmp/vnx_expect_3_$$.log

expect -c "
set timeout 5
spawn ssh user@$1
expect \"password:\"
send \"pass\r\"
expect \"~\]\\\$\"
send \"server_sysstat $2\r\"
expect \"~\]\\\$\"
send \"server_df server_2 | grep servername | awk \'{print \\\"servername_used:\\\" \\\$3 \\\" servername_available:\\\" \\\$4 \\\" servername_percentage:\\\" \\\$5}\'\r\"
expect \"~\]\\\$\"
send \"exit\r\"
" > $TMP

#cat $TMP | awk '/threads/,/cpu/' | sed "s/=/:/" | sed "s/\s//g" | sed "s/_%//g" | sed "s/I\/J\/Z//g" | sed "s/(kB)//g" > $TMP2
cat $TMP | grep -A 3 'threads runnable' | sed "s/\s//g" > $TMP2
cat $TMP | grep -A 0 'cpu idle_%' | sed "s/\s//g" | awk -F'=' '{print "cpu=" 100-$2}' >> $TMP2
cat $TMP2 | sed "s/=/:/g" | sed "s/_%//g" | sed "s/I\/J\/Z//g" | sed "s/(kB)//g" > $TMP3
cat $TMP | grep '^servername' | sed "s/%//g" >> $TMP3
cat $TMP3 | sed ':loop N; $!b loop; ;s/\n/ /g'

rm $TMP
rm $TMP2
rm $TMP3

出力
[sysuser ~]$ /bin/sh /usr/local/share/cacti/scripts/vnx_sysstat.sh 192.168.0.1 server_2
threadsrunnable:14 threadsblocked:5162 threads:1 memoryfree:3237370 cpu:11 servername_used:7829472280 servername_available:1580392792 servername_percentage:83%

expect で自動ログインしパスワードを変更するスクリプト

expect で自動ログインしパスワードを変更するスクリプトのサンプル

  • 引数1: 接続先
  • 引数2: 現在のrootパスワード
  • 引数3: 新しいrootパスワード
    1. expect -c でexpect開始
    2. while で、タイムアウトを待ちながら、ssh初回接続時の yes/no 確認プロンプトを確認。パスワードを聞かれれば、パスワードを送信
    3. プロンプトが出たら、su - で特権に昇格
    4. root パスワード変更コマンド発行
    5. 新しいrootパスワードを送信後、interact で手入力を待つ
    6. successfully という文字列が出たら、成功と判断し exit

#!/bin/sh

PR='(#|\\$) $' # regular prompt

expect -c "
set timeout 10
spawn ssh sysuser@$1
while (1) {
expect timeout { break } \"(yes/no)?\" { sleep 1;send \"yes\r\" } \"word: \" { sleep 1;send \"sysuser\r\";break }
}
expect -re \"$PR\"; sleep 1; send \"su -\r\"
expect -re \":\"; sleep 1; send \"$2\r\"
expect -re \"#\"; sleep 1; send \"passwd root\r\"
expect -re \"word:\"; sleep 1; send \"$3\r\"
expect -re \"word:\"; interact -o -nobuffer successfully return
expect -re \"#\"; sleep 1; send \"exit\r\"
expect -re \":\"; sleep 1; send \"exit\r\"
"