我正在使用Powershell编写部署脚本。使用Copy-Item
命令不会在两次运行之间提供相同的结果,即使使用相同的数据也是如此。(似乎不是幂等的)
有关我的意思的示例,请参见下面的结果。我意识到我可以C:\products
在复制“新”版本之前删除其中的文件,但是我对这在Powershell中是否是预期的行为感到好奇。(我假设是这样)
我宁愿学习“正确”的使用方式,也Copy-Item
不要因为缺乏知识而乱砍。
我尝试使用target\*
path代替,target
但是这将我的lib
文件夹分解到的根中showcase
,即使带该-Recurse
标志我也没想到。
C:\products
- showcase
- showcase.jar
- logback.jar
- foo.jar
- junit.jar
- etc, etc
我也对这里的文档(特别是示例7,10和11)感到困惑,因为7使用了该-Recurse
标志,而11使用了该标志。同时,示例10表示:
如果scripts文件夹在子文件夹中包含文件,则这些子文件夹将在其文件树完好无损的情况下被复制。
但也不会指定任何递归标志。
C:\products
- backup
C:\products
- showcase
- showcase.jar
- lib
- <dependencies for showcase.jar>
- backup
<empty>
# Expected, as there wasn't a prior deployment yet.
C:\products
- showcase
- showcase.jar
- lib
- <dependencies for showcase.jar>
- target
- showcase.jar
- lib
- <dependencies for inner showcase.jar>
- backup
- showcase
- showcase.jar
- lib
- <dependencies for "old" showcase.jar>
# Expected, the old version was backed up
./deploy.ps1 -hostname foobar (it's a remote server)
param( [String]$hostname, [switch]$debug )
$folder_to_copy = "target"
$init_file = "./init.ps1"
function Backup-Binary ( [String]$source, [String]$name, [String]$dest ) {
$FullyQualifiedSourcePath = "$source\$name"
if (Test-Path $FullyQualifiedSourcePath) {
Write-Host "Backing up $FullyQualifiedSourcePath to the destination $dest"
Copy-Item -Recurse -Force -Path $FullyQualifiedSourcePath -Destination $dest -ErrorAction Stop
} else {
Write-Output "Directory $FullyQualifiedSourcePath didn't exist. May be an initial deployment. Continuing with deployment."
}
}
function Verify-Env ([String]$env_var) {
$check = [Environment]::GetEnvironmentVariable($env_var)
if ($check -eq $null) {
Write-Error "$env_var environment variable doesn't exist. Exiting program."
exit 1
}
}
function Deploy-Local {
# Checks that the given string exists as an Environment variable
Verify-Env "DEPLOY_DRIVE"
Verify-Env "CI_PROJECT_NAME"
# C:\products or D:\products *most* of the time.
$root = "$env:DEPLOY_DRIVE\products"
$destination = "$root\$env:CI_PROJECT_NAME"
$backup_loc = "$root\backup"
# Removes prior binaries
Backup-Binary -source $root -name $env:CI_PROJECT_NAME -dest $backup_loc
# Copy binary locally since we're deploying to local machine.
Copy-Item -Recurse -Force -Path $folder_to_copy -Destination $destination -ErrorAction Stop
# Run the init script the developer has written
Invoke-Expression "$init_file" -ErrorAction Stop
}
function Deploy-Remote {
$session = New-PSSession -ComputerName $hostname
$DEPLOY_DRIVE = Invoke-Command -Session $session -ScriptBlock {
[Environment]::GetEnvironmentVariable("DEPLOY_DRIVE")
} -ErrorAction Stop
$root = "$DEPLOY_DRIVE\products"
$destination = "$root\$env:CI_PROJECT_NAME"
$backup_loc = "$root\backup"
Write-Host "$root = root $destination = destination $backup_loc = backup_location"
Invoke-Command -Session $session -ScriptBlock ${function:Backup-Binary} -ArgumentList $root,$env:CI_PROJECT_NAME,$backup_loc -ErrorAction Stop
Copy-Item -Recurse -Force -ToSession $session -Path $folder_to_copy -Destination $destination -ErrorAction Stop
Invoke-Command -Session $session -FilePath $init_file -ErrorAction Stop
Remove-PSSession $session -ErrorAction Stop
}
if ( $hostname.ToLower() -eq $env:COMPUTERNAME.ToLower() ) {
Deploy-Local
} else {
Deploy-Remote
}
@huffstler:
是的,但是与#2934相同,只是在一个更大的命令中:
- 当为subdir时。a正在被复制,$ b还不存在,因此a的内容被直接复制到$ b中(上述行为(a))。
- 通过时间子目录。复制b时,$ b已经存在,那就是出现不一致的时候:b的内容复制到$ b / b(上面的行为(b))。
因此,如果再次运行该命令,则可以实现所需的行为。
鉴于当前的行为,您可以按照以下方法解决此问题:
Get-ChildItem -Path $a | ForEach-Object { New-Item -Force -Type Directory $b } { Copy-Item -Recurse -Path $_.FullName -Destination $b }
但是,更大的问题是,应该针对行为(a)还是行为(b)解决这种矛盾。
您明确预期(a),但其他人根据xcopy可能会有不同的期望。
坦白说,我困惑于发现与Unix世界中的Copy-Item -Recurse(cp -R)相同的不一致之处。
当前获得可预测行为的唯一方法是:
确保目标目录。已经存在。
然后,根据您是要行为(a)还是(b):
要获得行为(a):明确指定源目录的内容:
Copy-Item -Recurse -Force $a/* $b
请注意需要使用-Force,以确保也复制了隐藏项。
在Unix上使用cp,您可以更简单地
$a/.
做到这一点,但这在PowerShell中不起作用。获得行为(b):无需采取进一步措施。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句