无法在PowerShell远程会话中访问UNC路径

11

我无法在本地计算机的Powershell远程会话中访问服务器上的UNC路径,但可以直接从服务器的Cmd提示符中使用它们。

事实上,我已登录到服务器并将UNC路径映射为本地驱动器(例如X:)。使用登录时重新连接选项。

我有一个批处理文件位于此X:驱动器中,我想要在本地脚本中使用invoke命令远程运行它。但是,它失败了。

它说“找不到驱动器。不存在名为X的驱动器”。

而且,当我尝试在scriptblock中使用net use命令映射驱动器时,它也会抛出错误-系统错误1223-本地命令错误。

我使用管理员凭据登录到此服务器。

请问有人能帮我解决吗?我只想远程运行存储在此UNC路径中的脚本?

另外,当我将UNC路径映射为服务器上的本地驱动器时,为什么无法在PS远程会话中使用它?

先行致谢。 TS


你尝试过在文件路径中的"x"后面加上"$"吗?就像这样:"\\ServerName\X$\Folder\PowershellFile.ps1" - Richard
我已经尝试过了,但是没有成功。 - user2610958
3个回答

12

这里有三个不同的事情需要注意。

1和3. 当你登录交互式界面时才会映射驱动器,因此当你远程连接到另一台计算机,映射驱动器,然后注销/断开连接时,该映射驱动器将被断开。除了在交互式GUI用户会话中,您不能依赖于自己未创建的映射驱动器。在脚本或任何远程会话中,只需使用UNC路径 - 这更加可靠。

2. 当您尝试在远程PS会话中映射驱动器时,您会遇到所谓的“双跳”问题。有一个解决方案,但需要额外的设置。请参阅Double hop access to copy files without CredSSP


1
您提供的信息非常有用。我刚刚想到了另一种方法 - 只需将凭据传递给您在脚本块中使用的UNC路径,作为net use命令的一部分 - 请参阅Net Use命令的语法。这解决了我的问题。我使用Get-Credntial cmd-let从用户那里获取AD凭据,并应用于所有服务器。要将用户名和密码传递给net use cmd - 我使用GetNetworkCredntial().Username和GetNetworkCredential().Password,它起作用了 - 此密码是明文的。您甚至可以将其打印在输出控制台上。 - user2610958
PS并不像我想象的那样安全,即使你使用Get-Credential命令,也可以获取明文密码。因此,我无法实现我的脚本。明文密码在企业中是不安全的。 - user2610958

8
alroc的有用回答很好地解释了问题,并指出了通过先前配置来解决问题的资源。
  • 这篇博客文章中可以找到关于基础问题——臭名昭著的Kerberos 双跳问题以及可用解决方案的概述。

至于在远程会话(PSv3+)中访问网络共享的临时解决方案

  • 通过变量传递会话的凭据;例如,-Credential $cred

  • 然后在会话中也使用这些凭据 - 例如,作为$using:cred - 使用New-PSDrive建立会话范围的辅助驱动器,映射网络位置。
    一旦映射了驱动器,目标位置就可以访问 - 无论是通过驱动器名称还是直接通过UNC路径。

注意:这是OP本人发现的方法的一个变化,并在alroc的回答评论中简要讨论,只是使用New-PSDrive而不是net use,这样就无需以纯文本形式检索密码。

以下示例代码演示了如何在远程会话中从网络共享运行脚本:

# A sample script to run from a network share on a remote computer.
$script = '\\server-001\install\Install-Agent.ps1'

# A sample target computer.
$computer = 'ws-002'

# Obtain the credentials for the remote session and store them in a variable.
$cred = Get-Credential $env:USERNAME

Invoke-Command -ComputerName $computer -Credential $cred {
  # Map the target network share as a dummy PS drive using the passed-through
  # credentials.
  # You may - but needn't - use this drive; the mere fact of having established
  # a drive with valid credentials makes the network location accessible in the
  # session, even with direct use of UNC paths.
  $null = New-PSDrive -Credential $using:cred -Name dummy -Root (Split-Path -Parent $using:script) -PSProvider FileSystem
  # Invoke the script via its UNC path.
  & $using:script
}

注意:
- $null = ... 抑制了 New-PSDrive 的输出(它会输出一个描述新创建驱动器的对象)。 - 由于 New-PSDrive 创建的驱动器不是持久化的(除非您传递 -Persist 参数),因此无需显式地删除虚拟驱动器,但您可以使用 Remove-PSDrive 命令进行删除。 - 注意,PS 驱动器定义是有范围限制的,只有调用范围及其后代能看到该驱动器;这使得您可以将语句包装在 & { ... } 中,在子范围中调用它们,这意味着在该代码块被退出时,自动撤销在该块内创建的 PS 驱动器。

-2

您可以尝试通过调用 WmiMethod 打开脚本:

$cmd = "CMD.EXE /c *\\\servername\somefolder\yourscript*.cmd" 

Invoke-WmiMethod -class Win32_process -name Create -ArgumentList $cmd -ComputerName *servername*

请注意,这将在服务器上运行脚本。您可以做更多的事情,比如在将软件包本地复制到远程机器后远程安装软件包。
希望这有所帮助!

1
这种方法对我没有解决问题。我相信双跳问题仍然存在。直接从WMI使用它,像这样:"powershell -ExecutionPolicy Bypass -file "\server\path\file.ps1." Powershell抱怨找不到文件。也尝试将其作为嵌入式命令放在远程服务器上的.bat脚本中。当直接从服务器运行(ps1或bat-> ps1)时,它可以工作。在所有情况下,由PowerShell看到的用户名都是相同的。 - crokusek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接