如何检查远程计算机/DFS共享目录并按需创建,解决脚本挂起问题?
PowerShell远程目录检查与文件复制脚本挂起问题修复
问题场景
脚本需从中央管理服务器运行,需求如下:
- 检查多台远程计算机上是否存在BA Client目录(
\\$server\C$\progra~1\Tivoli\TSM\Baclient) - 若该目录存在,检查DFS共享中以计算机名命名的目录下是否存在
baclient子目录,不存在则创建 - 将远程目录下的
.opt文件复制至DFS共享路径
当前脚本在源目录不存在或远程机器不可达时会出现无响应挂起,原脚本内容如下:
$serverlist = Get-Content ".\serverlist.txt" foreach ($server in $serverlist) { #If this folder exists in this host if (Test-Path "\\$server\C$\progra~1\Tivoli\TSM\Baclient" -eq $true )) #If this folder exists on DFS share if (-not (Test-Path "\\domainname\dfs\Systemer\TSMRepository\servere OPT Files\$server\baclient")) { Write-Host "Creating new folder...... " New-Item -Path "\\domainname\dfs\Systemer\TSMRepository\servere OPT Files\$server\baclient" -ItemType Directory } sleep -Seconds 4 Write-Host "Copying the file(s) to destination...." Copy-Item -Path "\\$server\C$\progra~1\Tivoli\TSM\Baclient\*.opt" -Destination "\\domainname\dfs\Systemer\TSMRepository\servere OPT Files\$server\baclient\\" -Verbose }
问题分析
- 语法与逻辑错误:第一个
if语句多了一个闭合括号),且没有用{}包裹后续代码块。这导致无论远程目录是否存在,都会执行创建DFS目录和文件复制操作,完全违背需求逻辑。 - 远程访问无超时控制:
Test-Path访问远程共享时默认超时时间较长,当远程机器离线、无权限或目录不存在时,会长时间等待导致脚本挂起。 - 无异常处理:复制文件时如果源目录不存在,
Copy-Item会抛出错误甚至持续等待,没有错误捕获机制。
修复后的脚本
以下是优化后的脚本,解决了挂起问题并修正了逻辑:
$serverlist = Get-Content ".\serverlist.txt" $dfsRootPath = "\\domainname\dfs\Systemer\TSMRepository\servere OPT Files" $sourcePathTemplate = "\\{0}\C$\progra~1\Tivoli\TSM\Baclient" $destPathTemplate = "{0}\{1}\baclient" foreach ($server in $serverlist) { Write-Host "正在处理服务器: $server" -ForegroundColor Cyan # 先检查远程服务器是否在线,快速过滤不可达机器 if (-not (Test-Connection -ComputerName $server -Count 1 -Quiet -TimeoutSeconds 2)) { Write-Host "服务器 $server 离线,跳过处理" -ForegroundColor Red continue } $sourcePath = $sourcePathTemplate -f $server # 检查远程目录是否存在,添加错误抑制避免长时间等待 if (Test-Path -Path $sourcePath -ErrorAction SilentlyContinue) { $destPath = $destPathTemplate -f $dfsRootPath, $server # 创建DFS目标目录(如果不存在) if (-not (Test-Path -Path $destPath)) { try { New-Item -Path $destPath -ItemType Directory -Force -ErrorAction Stop | Out-Null Write-Host "已创建目录: $destPath" -ForegroundColor Green } catch { Write-Host "创建目录失败: $_" -ForegroundColor Red continue } } # 复制.opt文件 try { Copy-Item -Path "$sourcePath\*.opt" -Destination $destPath -Verbose -ErrorAction Stop Write-Host "文件复制完成: $server" -ForegroundColor Green } catch { Write-Host "文件复制失败: $_" -ForegroundColor Red } } else { Write-Host "远程目录不存在: $sourcePath" -ForegroundColor Yellow } Start-Sleep -Seconds 1 # 适当缩短等待时间,避免不必要的延迟 }
优化点说明
- 前置在线检查:用
Test-Connection快速判断远程机器是否可达,超时2秒,避免在离线机器上浪费时间。 - 修正逻辑结构:将创建目录和复制操作放在远程目录存在的
if块内,符合需求逻辑。 - 错误处理:对创建目录和复制文件操作添加
try/catch捕获异常,避免脚本挂起。 - 路径模板化:将重复路径定义为模板,提高脚本可维护性。
- 缩短等待时间:将原4秒等待缩短为1秒,减少不必要的延迟。
内容的提问来源于stack exchange,提问作者MACH
相关产品推荐
相关产品推荐

