使用 PuTTY Plink 执行 .ps1 文件时出现意外字符
Unexpected char when executing .ps1 file using PuTTY Plink
我正在远程执行一些脚本以使用 putty 中的 Plink 工具从服务器获取信息。当我使用 .ps1 文件时,问题就来了,因为一个 '?'出现在开头,使第一行不正确,但 .bat 文件可以正常工作。
比如我要打印一个文件的内容:
GetDate.bat:
type C:/Data/DateOfCompilation.txt
然后:
PS C:/Users/MyUser> plink -ssh <User>@<IP> -i C:\Key.ppk -m C:\Scripts\GetDate.bat
10/09/2018 14:32:02,72
一切顺利
GetDate.ps1:
Get-Content -Path C:/Data/DateOfCompilation.txt
执行:
PS C:/Users/MyUser> plink -ssh <User>@<IP> -i C:\Key.ppk -m C:\Scripts\GetDate.ps1
?Get-Content : The term '?Get-Content' 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 line:1 char:1
+ ?Get-Content -Path C:/Data/DateOfCompilation.txt
+ ~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (?Get-Content:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
此外,如果我添加更多代码,其他行工作正常,它只是第一行失败,在开头添加 '?'。
(但是,运行 本地脚本工作正常)
我有其他 ps1 脚本扩展得更多,所以只使用 bat 文件不是最好的选择。
我查看了文档、其他论坛和此处,但我找不到任何东西。也许我对 ps1 个文件一无所知。
检查GetDate.ps1
开头是否有UTF-8 BOM - 如果有则去掉
尽管问题的根本原因可能是您对 Plink 的 -m
开关的误解。它使 Plink 读取文件并将其内容(并且仅发送内容)发送到服务器。服务器永远不会知道文件扩展名是什么。所以使用 .ps 与 .bat 没有任何意义。无论扩展名是什么,该文件都将由您的 Windows SSH 服务器的默认 shell 解释。什么是PowerShell(根据报错信息)。
因此,即使您在 .bat 文件中的 type
命令也是由 PowerShell 执行的,而不是由 cmd.exe
执行的。在 PowerShell 中,type
是 Get-Content
.
的别名
您的 .bat 文件之所以有效,很可能是因为它没有 BOM,而您的 .ps1 有 BOM。如果您使用 PowerShell 执行 .ps1,它会正确处理 BOM。但是您没有使用 PowerShell 执行 .ps1,您正在执行它的内容,在这种情况下,BOM 可能会导致问题。
两者的区别基本上是:
powershell.exe -File GetDate.ps1
和
powershell.exe < GetDate.ps1
两者基本相同,但后者因 BOM 而失败,而第一个正确处理。
我正在远程执行一些脚本以使用 putty 中的 Plink 工具从服务器获取信息。当我使用 .ps1 文件时,问题就来了,因为一个 '?'出现在开头,使第一行不正确,但 .bat 文件可以正常工作。
比如我要打印一个文件的内容:
GetDate.bat:
type C:/Data/DateOfCompilation.txt
然后:
PS C:/Users/MyUser> plink -ssh <User>@<IP> -i C:\Key.ppk -m C:\Scripts\GetDate.bat
10/09/2018 14:32:02,72
一切顺利
GetDate.ps1:
Get-Content -Path C:/Data/DateOfCompilation.txt
执行:
PS C:/Users/MyUser> plink -ssh <User>@<IP> -i C:\Key.ppk -m C:\Scripts\GetDate.ps1
?Get-Content : The term '?Get-Content' 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 line:1 char:1
+ ?Get-Content -Path C:/Data/DateOfCompilation.txt
+ ~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (?Get-Content:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
此外,如果我添加更多代码,其他行工作正常,它只是第一行失败,在开头添加 '?'。
(但是,运行 本地脚本工作正常)
我有其他 ps1 脚本扩展得更多,所以只使用 bat 文件不是最好的选择。
我查看了文档、其他论坛和此处,但我找不到任何东西。也许我对 ps1 个文件一无所知。
检查GetDate.ps1
开头是否有UTF-8 BOM - 如果有则去掉
尽管问题的根本原因可能是您对 Plink 的 -m
开关的误解。它使 Plink 读取文件并将其内容(并且仅发送内容)发送到服务器。服务器永远不会知道文件扩展名是什么。所以使用 .ps 与 .bat 没有任何意义。无论扩展名是什么,该文件都将由您的 Windows SSH 服务器的默认 shell 解释。什么是PowerShell(根据报错信息)。
因此,即使您在 .bat 文件中的 type
命令也是由 PowerShell 执行的,而不是由 cmd.exe
执行的。在 PowerShell 中,type
是 Get-Content
.
您的 .bat 文件之所以有效,很可能是因为它没有 BOM,而您的 .ps1 有 BOM。如果您使用 PowerShell 执行 .ps1,它会正确处理 BOM。但是您没有使用 PowerShell 执行 .ps1,您正在执行它的内容,在这种情况下,BOM 可能会导致问题。
两者的区别基本上是:
powershell.exe -File GetDate.ps1
和
powershell.exe < GetDate.ps1
两者基本相同,但后者因 BOM 而失败,而第一个正确处理。