none
Start-Job について RRS feed

  • 質問

  • PowerShell スクリプト(zzzz.ps1)で、以下の通りにStart-Job を利用して、
    別のPowerShell スクリプト(yyyyy.ps1)を読みだしております。

    zzzz.ps1の中身---------------------------------------------------
    $bbbb=$args[0]
    Start-Job -FilePath C:\yyyyy.ps1 -ArgumentList $bbbb
    -------------------------------------------------------------------

    yyyyy.ps1の中身--------------------------------------------------
    $cccc=$args[0]
    echo $cccc >> C:\tmp1.txt
    --------------------------------------------------------------------

    powershellでは、以下のコマンドを実行すれば問題なく動作できます。

    zzzz.ps1 1111

    ただ、zzzz.ps1をコマンドプロンプトで以下のコマンドで実行すると
    yyyyy.ps1 が実行されない。もしくは「Powershellは動作を停止しました」と
    ポップアップ画面が表示されてうまく動作できません。

    powershell -C "C:\zzzz.ps1 1111

    Start-Job の記述に誤りがあると思うのですが、どのように修正すればわからい状況です。
    大変恐縮ですが、もしわかる方がいれば、ご教授をお願いしたいと考えております。

    2015年7月1日 8:53

回答

  • ジョブの終了を待機せず、きちんとバックグラウンドで処理を継続させる方法を考えました。

    zzzz.ps1を

    $bbbb=$args[0]
    $s=New-PSSession -ComputerName . 
    Invoke-Command -Session $s -FilePath C:\yyyyy.ps1 -ArgumentList $bbbb -AsJob 

    のように変更します。

    コマンドプロンプトでzzzz.ps1を実行する方法は以前と同じですが、コマンドプロンプトは管理者権限で実行するようにしてみてください。

    PowerShell 3.0以降だと、PSSessionは作成元のプロセスが終了しても、作成先では保持されることを利用しています。
    今回の場合は作成元と作成先は同一(ローカルコンピュータ)ですが、PSSession作成先に別プロセスが生成され、そこでバックグラウンドジョブが走るようになるので、作成元のプロセスが終了しても、処理は継続するわけです。

    ただしローカルコンピュータにPSSessionを作成するには管理者権限が必要なので、コマンドプロンプト起動時に管理者権限が必要となります。

    • 回答としてマーク libra441 2015年7月3日 8:34
    2015年7月2日 1:56
    モデレータ

すべての返信

  • ジョブの終了前にcmd.exeから起動したPowerShell.exeが終了してしまっているのが原因かと思います。

    zzzz.ps1中のジョブ実行部分を、

    Start-Job -FilePath C:\yyyyy.ps1 -ArgumentList $bbbb | Wait-Job

    として、ジョブの終了を待機するようにしてみてはいかがでしょうか。

    ただし、当然ながらyyyyy.ps1実行の終了を待機することになるので、ジョブとして実行している意味はあまりなくなってしまうかもしれないです。

    2015年7月1日 9:44
    モデレータ
  • こちらの環境では「Powershellは動作を停止しました」というエラー自体がなぜが出てくれなかったのですが、tmp1.txtの出力が無かったのでいろいろ悩んでいたところ、zzzz.ps1だけ、以下のようにすれば、「tmp1.txtの出力」自体はできるようになりました。

    $bbbb=$args[0]
    $command="C:\yyyyy.ps1"
    Start-Job -ScriptBlock {param($command)& $command } -argumentList $bbbb

    ただし、libra441さんの意図にかなう処理なのかどうかはわかりませんので、あくまでご参考までに書かせていただきました。
    (私自身、このスクリプトブロックが意味するところをよく理解していません・・・・)。
    ※このコードの3行目は Start-Job のScriptBlock に変数の値を渡す方法 の牟田口大介さんのご回答でたどり着いたものです。



    • 編集済み Fuzitaman 2015年7月23日 5:06 相当おかしなことを書いている為
    2015年7月1日 10:30
  • ジョブの終了を待機せず、きちんとバックグラウンドで処理を継続させる方法を考えました。

    zzzz.ps1を

    $bbbb=$args[0]
    $s=New-PSSession -ComputerName . 
    Invoke-Command -Session $s -FilePath C:\yyyyy.ps1 -ArgumentList $bbbb -AsJob 

    のように変更します。

    コマンドプロンプトでzzzz.ps1を実行する方法は以前と同じですが、コマンドプロンプトは管理者権限で実行するようにしてみてください。

    PowerShell 3.0以降だと、PSSessionは作成元のプロセスが終了しても、作成先では保持されることを利用しています。
    今回の場合は作成元と作成先は同一(ローカルコンピュータ)ですが、PSSession作成先に別プロセスが生成され、そこでバックグラウンドジョブが走るようになるので、作成元のプロセスが終了しても、処理は継続するわけです。

    ただしローカルコンピュータにPSSessionを作成するには管理者権限が必要なので、コマンドプロンプト起動時に管理者権限が必要となります。

    • 回答としてマーク libra441 2015年7月3日 8:34
    2015年7月2日 1:56
    モデレータ
  • 上記の件について、ご回答ありがとうございます。

    今回利用しているPowerShellのバージョンが2のためなのかわかりませんが
    ご連絡頂きました内容でスクリプトを修正して、
    コマンドプロンプトを管理者権限で開いて、実行してみたのですが、
    以下のエラーが出力されてしまい、実行できませんでした

    これは、PowerShellのバージョンをあげる必要があるのでしょうか。

    -----------------------------------------------------------------------------------------------

    [localhost] Connecting to remote server failed with the following error message
     : ???????????????????????????? ???????????????????????????????????????????? ??
    ????????? WS-Management ???? (??? IIS ??? WinRM) ??????????????????????? ???? W
    inRM ????????????? ?????????????????WinRM ??????????????????: "winrm quickconfi
    g" For more information, see the about_Remote_Troubleshooting Help topic.
        + CategoryInfo          : OpenError: (System.Manageme....RemoteRunspace:Re
       moteRunspace) [], PSRemotingTransportException
        + FullyQualifiedErrorId : PSSessionOpenFailed
    Invoke-Command : Cannot validate argument on parameter 'Session'. The argument
    is null or empty. Supply an argument that is not null or empty and then try the
     command again.
    At C:\zzzz.ps1:3 char:24
    + Invoke-Command -Session <<<<  $s -FilePath C:\yyyyy.ps1 -ArgumentList $bbbb -
    AsJob
        + CategoryInfo          : InvalidData: (:) [Invoke-Command], ParameterBind
       ingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.Power
       Shell.Commands.InvokeCommandCommand

    -----------------------------------------------------------------------------------------------

    2015年7月3日 1:14
  • 上記の件について、ご回答ありがとうございます。

    ご連絡頂きました内容をもとに、スクリプトは修正してみましたが
    「Powershellは動作を停止しました」というエラーはでないのですが、
    「yyyyy.ps1」が実行されていないのか、tmp1.txtの出力ができませんでした。

    これは、やはり、今回利用しているPowerShellのバージョンが2のためできていないと考えた方がいいのでしょうか

    2015年7月3日 1:20
  • PSSessionを張るには、PS Remotingの構成が必要です。そのためにはチキンさんがご提示の方法か、Enable-PSRemotingコマンドレットを実行します。

    ただしPSSessionを使って親プロセス終了後もジョブを継続実行させる方法は、いずれにせよ、PowerShell 3.0以上が必要となります。

    Wait-Jobを使う方法は2.0でも大丈夫かと思います。

    2015年7月3日 1:43
    モデレータ
  • PowerShell をバージョン 3.0 にしたら、うまく動作できましました。

    ご回答ありがとうございます。

    2015年7月3日 8:35