ようへいの日々精進XP

よかろうもん

Ansible で Windows のタスクスケジュールを登録する際のメモ(毎分のタスク登録ってどうするの?)

ども、かっぱです。

tl;dr

win_scheduled_task だけではやりたい事を実践出来なかったので、自分なりに試行錯誤したのでメモっておく。


参考


memo

試した環境

% ansible --version
ansible 2.0.1.0
  config file = 
  configured module search path = Default w/o overrides

win_scheduled_task モジュールで基本的にはなんとかなる

こちらのドキュメントのサンプルは以下の通り。

win_scheduled_task: name="TaskName" execute="cmd" frequency="daily" time="9am" description="open command prompt" path="example" enable=yes state=present user=SYSTEM

5 分ごとに実行させたいタスクの登録をどうするか

自分の探し方が悪いのかもしれないけど、上述の win_scheduled_task モジュールでは毎分で何かをさせるようなタスクを登録する方法を見つけることが出来なかった。

結局、自分は以下のような 2 種類の PowerShell スクリプトscript モジュールで叩かせるようにした。

#
# PowerShell Script(タスクの存在を確認)
# check_task.ps1 ${タスク名}
#
Get-ScheduledTask -TaskName $args[0] | select -First 1 TaskName -ExpandProperty TaskName

この PowerShell スクリプトを roles/${role_name}/files 以下に保存する。

#
# PowerShell Script(タスクの登録)
# regist_task.ps1 ${タスク名}
#
$Execute = 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe'
$Argument = '-Command "C:\path\to\scripts' +  $args[0] + '.ps1"'
$User = 'SYSTEM'
$Trigger = New-ScheduledTaskTrigger -Once -at '00:00:00' -RepetitionInterval '00:05:00' -RepetitionDuration ([timespan]::MaxValue)
$TaskPath = 'mytask'
$TaskName = $args[0]
$Description =  $args[0]

$Action = New-ScheduledTaskAction -Execute $Execute -Argument $Argument
$Settings = New-ScheduledTaskSettingsSet -Compatibility Win8 -Hidden
$principal = New-ScheduledTaskPrincipal -UserId $User -LogonType ServiceAccount

Register-ScheduledTask `
  -TaskPath $TaskPath `
  -TaskName $TaskName `
  -Description $Description `
  -Trigger $Trigger `
  -Action $Action `
  -Settings $Settings `
  -Principal $Principal

同じく、この PowerShell スクリプトを roles/${role_name}/files 以下に保存する。

  • 実際の Ansible タスク
#
# mytask schedule
#
- name: 登録済みタスクが無いかをチェックする
  script: files/check_task.ps1 mytask
  register: task_info

- name: デバッグ出力
  debug: var=task_info.stdout

- name: PowerShell スクリプトを利用してタスクを登録する
  script: files/regist_task.ps1 mytask
  when: task_info.stdout != "mytask\r\n"

実際に登録してみる

以下のように Playbook を実行してタスクを登録する。

% ansible-playbook -i inventories/hosts default.yml

PLAY ***************************************************************************

TASK [setup] *******************************************************************
ok: [my-sandbox]

TASK [regist_task : 登録済みタスクが無いかをチェックする] ****************************************
changed: [my-sandbox]

TASK [regist_task : デバッグ出力] ****************************************************
ok: [my-sandbox] => {
    "task_info.stdout": ""
}

TASK [regist_task : PowerShell スクリプトを利用してタスクを登録する] *****************************
changed: [my-sandbox]

PLAY RECAP *********************************************************************
my-sandbox                 : ok=4    changed=2    unreachable=0    failed=0

登録後...タスクスケジューラーを確認する。

f:id:inokara:20160323232348p:plain

再度、実行してみる。

% ansible-playbook -i inventories/hosts default.yml
PLAY ***************************************************************************

TASK [setup] *******************************************************************
ok: [my-sandbox]

TASK [regist_task : 登録済みタスクが無いかをチェックする] ****************************************
changed: [my-sandbox]

TASK [regist_task : デバッグ出力] ****************************************************
ok: [my-sandbox] => {
    "task_info.stdout": "mytask\r\n"
}

TASK [regist_task : PowerShell スクリプトを利用してタスクを登録する] *****************************
skipping: [my-sandbox]

PLAY RECAP *********************************************************************
my-sandbox                 : ok=3    changed=1    unreachable=0    failed=0

一応、冪等性が担保されて Skipping となっていることを確認。


以上

もっとエレガントな方法求む

毎分の処理をタスクスケジューラに追加する場合に本当に script モジュールで PowerShell を叩くしか無いのか疑わしい!

でも

勉強になりました。