Como adicionar dinamicamente tarefas a uma fila de trabalhos do PowerShell

3

Eu criei um script do PowerShell que copia todos os e-books que eu baixei para um diretório predeterminado, que é verificado periodicamente pelo meu gerente de e-book e adicionado à minha biblioteca. O script é executado imediatamente após cada download.

O problema é que, quando vários livros são baixados ao mesmo tempo ou quase ao mesmo tempo, o gerenciador de e-book é bloqueado e não responde.

Portanto, gostaria de enfileirar a cópia usando trabalhos do PowerShell, mas não sei como criar uma única fila (única simultaneidade) que cada trabalho subseqüente aguardará a conclusão de todos os trabalhos mais antigos.

Ou seja, gostaria que o script criasse um trabalho (vamos chamá-lo de "Book Job"), que verifica periodicamente a fila de Execução de Jobs do Book para ver se todos os Jobs mais antigos terminaram antes de serem executados. Quando estiver concluído, um trabalho do livro deve declarar que terminou de alguma forma que pode ser detectado por trabalhos de livros mais novos.

Alguém sabe como posso fazer isso? Eu vi uma pergunta semelhante aqui que eu estou olhando: tarefas de fundo do PowerShell , no entanto, no meu caso eu Estou executando o script várias vezes (após cada novo download).

    
por Mavaddat Javid 27.03.2018 / 01:39

1 resposta

3

Meu pensamento é estabelecer uma fila criando um arquivo de bloqueio por nova instância do seu script. Quando o script é executado, ele verifica um diretório dedicado ao rastreamento da fila para instâncias existentes do script. Se não houver nenhum, o script se adiciona à frente da fila, executa alguma ação (executa seu código) e, em seguida, limpa seu bloqueio. Se houver bloqueios, um novo será adicionado ao final da fila e a instância verificará incessantemente até que esteja na frente da fila.

Isso permite que você execute o mesmo script várias vezes, manipulando-se individualmente, verificando a fila disponível externamente.

Os arquivos de bloqueio são estruturados como Index, delimiter ("_"), ID do processo.

Clear-Host

function New-Lock ([int] $index) {
    $newLock = "$index" + "_" + $pid + ".lck"
    New-Item $queue$newLock | Out-Null
}

$queue = "C:\locks\"

# find the end of the stack
$locks = gci $queue *.lck | sort | select -expandproperty name

# if locks exist, find the end of the stack by selecting the index of the last lock
if($locks) {
    # gets the last lock file, selects the index by splitting on the delimiter
    [int]$last = [convert]::ToInt32(($locks | select -last 1).Split("_")[0],10)

    # add the lock to the end of the stack
    New-Lock ($last + 1)
}
# if no locks exist, create one at the top of the stack
else {
    New-Lock 0
}

# check if we're at the top of the stack
do {
    $locks = gci $queue *.lck | sort | select -expandproperty name

    # this is the PID on the top of the stack
    [int]$top = [convert]::ToInt32(($locks | select -first 1).Split("_")[1].Split(".")[0],10)
    write-verbose "not at the top..."
    sleep 1
} until ($pid -eq $top)

# if we're here, we've been to the top. it's our turn to do something
Write-Verbose "we've reached the top!"
# <do something. put your code here>
# might be good to add some Start-Sleep here
# </do something put your code here>

# now that we're done, let's delete our lock
gci $queue | select -first 1 | Remove-Item

Abaixo está um exemplo fictício de linha do tempo no qual você fez o download de três arquivos (eu escolhi PIDs aleatórios).

  • O arquivo 1 é baixado e inicia o script. Não há bloqueios existentes. Crie o bloqueio "0_19831". Estamos no topo da pilha, então seu código é executado. Este é um grande e-book, por isso o seu código de transferência de arquivos levará um minuto completo para ser executado.
  • O arquivo 2 é baixado e inicia o script. Bloqueio (s) existem. Criar bloqueio "1_332". Não estamos no topo da pilha, por isso vamos esperar no nosso do/until e continuar a verificar até sermos os primeiros da fila.
  • Arquivo 1 terminou a cópia. Excluir bloqueio "0_19831".
  • O arquivo 3 é baixado e inicia o script. Bloqueio (s) existem. Crie o bloqueio "2_7582". Não estamos no topo da pilha, espere até que estejamos.
  • Arquivo 2 terminou de copiar. Excluir bloqueio "1_332".
  • Arquivo 3 terminou de copiar. Excluir bloqueio "2_7582".

Esta solução não é à prova de balas, mas pode funcionar dependendo da escala.

    
por 27.03.2018 / 16:06