PowerShell脚本出现CommandNotFoundException错误,求排查解决
解决PowerShell中执行S3 cURL上传脚本的错误
问题背景
尝试使用以下基于bash风格的cURL脚本向AWS S3存储桶上传文件,但在PowerShell中执行时出现大量CommandNotFoundException等错误:
原脚本
#S3 parameters $S3KEY="AKIAYZL7ANTULMU355OD" $S3SECRET="AKIAYZL7ANTULMU355OD" $S3BUCKET="quixel-ml-team-data" $S3STORAGETYPE="STANDARD" #REDUCED_REDUNDANCY or STANDARD etc. $AWSREGION="us-west-2" file_path="C:\Users\DELL\AppData\Local\Temp\input_settings.txt" aws_path="seam-removal\" bucket="${S3BUCKET}" date=$(date -R) acl="x-amz-acl:private" content_type="application/x-compressed-tar" storage_type="x-amz-storage-class:${S3STORAGETYPE}" string="PUT\n\n$content_type\n$date\n$acl\n$storage_type\n/$bucket$aws_path${file_path##/*/}" signature=$(echo -en "${string}" | openssl sha1 -hmac "${S3SECRET}" -binary | base64) curl -s --retry 3 --retry-delay 10 -X PUT -T "$file_path" \ -H "Host: $bucket.${AWSREGION}.amazonaws.com" \ -H "Date: $date" \ -H "Content-Type: $content_type" \ -H "$storage_type" \ -H "$acl" \ -H "Authorization: AWS ${S3KEY}:$signature" \ "https://$bucket.${AWSREGION}.amazonaws.com$aws_path${file_path##/*/}"
报错信息
file_path=C:\Users\DELL\AppData\Local\Temp\input_settings.txt : The term 'file_path=C:\Users\DELL\AppData\Local\Temp\input_settings.txt' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At C:\Users\DELL\Desktop\Abdullah Chand\quixel-ml-khalid-chand\script_upload_to_aws_using_curl.ps1:11 char:1 + file_path="C:\Users\DELL\AppData\Local\Temp\input_settings.txt" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (file_path=C:\Us...ut_settings.txt:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException aws_path=seam-removal\ : The term 'aws_path=seam-removal\' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At C:\Users\DELL\Desktop\Abdullah Chand\quixel-ml-khalid-chand\script_upload_to_aws_using_curl.ps1:12 char:1 + aws_path="seam-removal\" + ~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (aws_path=seam-removal\:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException bucket=${S3BUCKET} : The term 'bucket=${S3BUCKET}' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At C:\Users\DELL\Desktop\Abdullah Chand\quixel-ml-khalid-chand\script_upload_to_aws_using_curl.ps1:13 char:1 + bucket="${S3BUCKET}" + ~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (bucket=${S3BUCKET}:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException date=$(date -R) : The term 'date=$(date -R)' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At C:\Users\DELL\Desktop\Abdullah Chand\quixel-ml-khalid-chand\script_upload_to_aws_using_curl.ps1:14 char:1 + date=$(date -R) + ~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (date=$(date -R):String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException acl=x-amz-acl:private : The term 'acl=x-amz-acl:private' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At C:\Users\DELL\Desktop\Abdullah Chand\quixel-ml-khalid-chand\script_upload_to_aws_using_curl.ps1:15 char:1 + acl="x-amz-acl:private" + ~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (acl=x-amz-acl:private:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException content_type=application/x-compressed-tar : The term 'content_type=application/x-compressed-tar' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At C:\Users\DELL\Desktop\Abdullah Chand\quixel-ml-khalid-chand\script_upload_to_aws_using_curl.ps1:16 char:1 + content_type="application/x-compressed-tar" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (content_type=ap...-compressed-tar:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException storage_type=x-amz-storage-class:${S3STORAGETYPE} : The term 'storage_type=x-amz-storage-class:${S3STORAGETYPE}' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At C:\Users\DELL\Desktop\Abdullah Chand\quixel-ml-khalid-chand\script_upload_to_aws_using_curl.ps1:17 char:1 + storage_type="x-amz-storage-class:${S3STORAGETYPE}" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (storage_type=x-...{S3STORAGETYPE}:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException string=PUT\n\n$content_type\n$date\n$acl\n$storage_type\n/$bucket$aws_path${file_path##/*/} : The module 'string=PUT' could not be loaded. For more information, run 'Import-Module string=PUT'. At C:\Users\DELL\Desktop\Abdullah Chand\quixel-ml-khalid-chand\script_upload_to_aws_using_curl.ps1:18 char:1 + string="PUT\n\n$content_type\n$date\n$acl\n$storage_type\n/$bucket$aw ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (string=PUT\n\n$...file_path##/*/}:String) [], CommandNotFoundException + FullyQualifiedErrorId : CouldNotAutoLoadModule signature=$(echo -en "${string}" | openssl sha1 -hmac "${S3SECRET}" -binary | base64) : The term 'signature=$(echo -en "${string}" | openssl sha1 -hmac "${S3SECRET}" -binary | base64)' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At C:\Users\DELL\Desktop\Abdullah Chand\quixel-ml-khalid-chand\script_upload_to_aws_using_curl.ps1:19 char:1 + signature=$(echo -en "${string}" | openssl sha1 -hmac "${S3SECRET}" - ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (signature=$(ech...inary | base64):String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException Invoke-WebRequest : Parameter cannot be processed because the parameter name 'T' is ambiguous. Possible matches include: -TimeoutSec -TransferEncoding. At C:\Users\DELL\Desktop\Abdullah Chand\quixel-ml-khalid-chand\script_upload_to_aws_using_curl.ps1:20 char:43 + curl -s --retry 3 --retry-delay 10 -X PUT -T "$file_path" \ + ~~ + CategoryInfo : InvalidArgument: (:) [Invoke-WebRequest], ParameterBindingException + FullyQualifiedErrorId : AmbiguousParameter,Microsoft.PowerShell.Commands.InvokeWebRequestCommand -H : The term '-H' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At C:\Users\DELL\Desktop\Abdullah Chand\quixel-ml-khalid-chand\script_upload_to_aws_using_curl.ps1:21 char:5 + -H "Host: $bucket.${AWSREGION}.amazonaws.com" \ + ~~ + CategoryInfo : ObjectNotFound: (-H:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException -H : The term '-H' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At C:\Users\DELL\Desktop\Abdullah Chand\quixel-ml-khalid-chand\script_upload_to_aws_using_curl.ps1:22 char:5 + -H "Date: $date" \ + ~~ + CategoryInfo : ObjectNotFound: (-H:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException -H : The term '-H' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At C:\Users\DELL\Desktop\Abdullah Chand\quixel-ml-khalid-chand\script_upload_to_aws_using_curl.ps1:23 char:5 + -H "Content-Type: $content_type" \ + ~~ + CategoryInfo : ObjectNotFound: (-H:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException -H : The term '-H' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At C:\Users\DELL\Desktop\Abdullah Chand\quixel-ml-khalid-chand\script_upload_to_aws_using_curl.ps1:24 char:5 + -H "$storage_type" \ + ~~ + CategoryInfo : ObjectNotFound: (-H:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException -H : The term '-H' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At C:\Users\DELL\Desktop\Abdullah Chand\quixel-ml-khalid-chand\script_upload_to_aws_using_curl.ps1:25 char:5 + -H "$acl" \ + ~~ + CategoryInfo : ObjectNotFound: (-H:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException -H : The term '-H' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At C:\Users\DELL\Desktop\Abdullah Chand\quixel-ml-khalid-chand\script_upload_to_aws_using_curl.ps1:26 char:5 + -H "Authorization: AWS ${S3KEY}:$signature" \ + CategoryInfo : ObjectNotFound: (-H:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException
错误原因分析
- 变量赋值语法错误:PowerShell中变量必须以
$开头,原脚本用了bash的变量名=值格式,PowerShell会把它当成命令执行,从而抛出CommandNotFoundException。 - 命令替换与工具差异:
- bash的
$(date -R)在PowerShell中需要用Get-Date生成RFC1123格式的日期; - PowerShell中
curl是Invoke-WebRequest的别名,不是真正的cURL工具,参数不兼容; - bash的字符串截取
${file_path##/*/}在PowerShell中需要用Split-Path命令实现。
- bash的
- 字符串转义差异:bash的
\n换行符在PowerShell双引号字符串中需要写成"n"`才能被正确解析。 - 签名生成逻辑差异:bash的
echo -en输出转义字符的方式在PowerShell中不适用,需要用[System.Text.Encoding]::UTF8.GetBytes()处理字符串后再生成签名。
修正后的PowerShell脚本
# S3参数配置 $S3KEY="AKIAYZL7ANTULMU355OD" $S3SECRET="AKIAYZL7ANTULMU355OD" $S3BUCKET="quixel-ml-team-data" $S3STORAGETYPE="STANDARD" # 可选值:REDUCED_REDUNDANCY、STANDARD等 $AWSREGION="us-west-2" # 文件路径配置 $file_path="C:\Users\DELL\AppData\Local\Temp\input_settings.txt" $aws_path="seam-removal\" $bucket=$S3BUCKET # 生成RFC1123格式的日期 $date = Get-Date -Format "r" # 请求头配置 $acl="x-amz-acl:private" $content_type="application/x-compressed-tar" $storage_type="x-amz-storage-class:$S3STORAGETYPE" # 获取文件名(替代bash的${file_path##/*/}) $file_name = Split-Path $file_path -Leaf # 构造签名用的字符串 $string = "PUT`n`n$content_type`n$date`n$acl`n$storage_type`n/$bucket$aws_path$file_name" # 生成HMAC-SHA1签名(base64编码) $hmacsha1 = New-Object System.Security.Cryptography.HMACSHA1 $hmacsha1.Key = [System.Text.Encoding]::UTF8.GetBytes($S3SECRET) $signatureBytes = $hmacsha1.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($string)) $signature = [System.Convert]::ToBase64String($signatureBytes) # 调用真正的cURL工具(如果已安装),或使用Invoke-WebRequest # 注意:确保系统已安装cURL并添加到环境变量,否则用下方的Invoke-WebRequest版本替代 curl.exe -s --retry 3 --retry-delay 10 -X PUT -T "$file_path" ` -H "Host: $bucket.$AWSREGION.amazonaws.com" ` -H "Date: $date" ` -H "Content-Type: $content_type" ` -H "$storage_type" ` -H "$acl" ` -H "Authorization: AWS $S3KEY:$signature" ` "https://$bucket.$AWSREGION.amazonaws.com$aws_path$file_name"
关键修改说明
- 变量赋值:所有变量前添加
$,符合PowerShell语法。 - 日期生成:用
Get-Date -Format "r"生成符合S3要求的RFC1123格式日期。 - 文件名截取:用
Split-Path $file_path -Leaf获取文件的纯文件名,替代bash的字符串截取语法。 - 签名生成:直接用PowerShell的加密类生成HMAC-SHA1签名,避免依赖openssl命令行工具,更稳定。
- cURL调用:用
curl.exe明确调用系统中的cURL工具,避免触发PowerShell的Invoke-WebRequest别名。
如果系统未安装cURL,可以用以下Invoke-WebRequest版本替代最后一段:
$headers = @{ "Host" = "$bucket.$AWSREGION.amazonaws.com"
相关产品推荐
相关产品推荐

