背景
今天在linux上搞后台任务,突发奇想powershell是否可以在关闭窗口后继续执行任务。
探究
以下的解决方法基本出自该帖https://www.v2ex.com/t/846505
测试脚本,每一秒打印一个数字,逐渐递增。
# PrintNumbers.ps1
# 初始化计数器
$i = 1
# 无限循环,直到脚本被中断
while ($true) {
# 打印当前数字
Write-Output '打印数字'
Write-Output $i
# 等待一秒
Start-Sleep -Seconds 1
# 增加计数器
$i++
}
Start-Process(不推荐)
使用pwsh,powershell7,如果用的是powershell,可以把pwsh改一下试试。
下面这个命令可以在不打开窗口的情况下执行命令,比较鸡肋的是,不太好管理。
Start-Process pwsh.exe -RedirectStandardOutput ./output.log -ArgumentList ".\count.ps1" -WindowStyle Hidden
Start-Job(未成功)
start-job其实还算是比较好用的,但是只能实现后台执行,把窗口关了就不行了。
有人可能想到了,如果使用Start-Process加上Start-Job那不就成了吗
理论上是可以的,但是start-process是通过-ArgumentList来达到类似于执行命令的手段,实际上正如其名他只能传参数,而不能直接传命令来执行。
那么,我们再编写一个脚本兴许就可以了,用start-process打开新进程,并使用-WindowStyle Hidden隐藏窗口,由于脚本执行完会自动关闭进程,因此我们写一个Read-Host "Press Enter to exit..."来阻塞这个进程,避免瞬间被杀死。
反正我没试成功。
procrun
将应用程序做成服务
感觉有些复杂,一时半会不好折腾
nssm
同样是做成服务
以下的命令是cd到nssm所在的路径执行的,pwsh是powershell 7的命令,如果没有更新过,将这里改成powershell即可。
# Desired name of the service
$serviceName = 'countTest'
# Get the full path to powershell.exe
$powershellPath = ( Get-Command pwsh ).Source
# The path to the script you want to run as a service
$serviceScriptPath = C:\Users\acer\Desktop\count.ps1
# The arguments to pass to the powershell executable each time the service starts
$args = '-ExecutionPolicy Bypass -NoProfile -File "{0}"' -f $serviceScriptPath
# Install the service using nssm
./nssm install $serviceName $powershellPath $args
./nssm set $ServiceName AppStdout "C:\Users\acer\Desktop\stdout.log"
./nssm set $ServiceName AppStderr "C:\Users\acer\Desktop\stderr.log"
# See that the service is registered and check its status
Get-Service $serviceName
总体上还是让人满意的,但是不知道为什么,日志里只有pwsh启动的输出,没有脚本的输出。这样看来,反而是第一个Start-Process成功了。
结语
windows终端多少还是吃力,就像开发GUI应用通常偏向于Windows一样,开发脚本和命令都是更偏向于linux的,windows的命令用起来还是难受。
虽然使用场景不多,但是windows这个后台运行实在是有些繁琐。