如何在PowerShell远程会话中编辑文件(PowerShell)

38

我正在使用PowerShell远程连接另一台计算机,非常好用。虽然可以做很多事情,但如何编辑文件呢?

PS C:\Users\guutlee> Enter-PSSession -ComputerName appprod

[appprod]: PS C:\Users\guutlee\Documents> cd \myapp

[appprod]: PS C:\myapp>

我该怎么在远程机器上打开一个文件编辑器,编辑文件呢?

[appprod]: PS C:\myapp> edit app.config

所以,从powershell.exe或powershell_ise.exe运行"edit "filename""看起来只是卡住了。

我唯一能想到的是退出PSSession并运行"start \webprod\c$\inetpub\myapp\web.config",这将打开Visual Studio。

[appprod]: PS C:\myapp> exit

PS C:\Users\guutlee> start \agobuild\c$\myapp\app.config

PS C:\Users\guutlee> Enter-PSSession -ComputerName appprod

[appprod]: PS C:\Users\guutlee\Documents> cd \myapp

[appprod]: PS C:\myapp> myapp.exe

当然,使用此方法需要重新查找文件,希望c$共享可用且可访问,并在需要继续工作时重新连接PSSession并重新查找工作目录。 这似乎不太优雅。

我可以尝试将其包装在一个函数中,但很难想象。。

那么,如何方便地使用远程PSSession编辑文件呢?

编辑

kbrimington的帖子让我想到了ssh的-X选项。对于powershell会话,能够将窗口化应用程序转发回原始窗口环境可能是个很棒的功能...

但我仍然很满意只是编辑文件。

编辑

使用vi、emacs、cmd和edit进行测试

PS C:\Users\Meredith> Enter-PSSession -ComputerName appprod

[appprod]: PS C:\Users\guutlee\Documents> C:\vim\vim72\vim filename.txt

[appprod]: PS C:\Users\guutlee\Documents> C:\emacs-23.2\bin\emacs.exe -nw filename.txt

emacs.exe:emacs:standard input is not a tty

+ CategoryInfo          \: NotSpecified: (emacs: standard input is not a tty:String) [], RemoteException

+ FullyQualifiedErrorId \: NativeCommandError

[appprod]: PS C:\Users\guutlee\Documents> cmd

The command prompt is opened but exits immediately in PowerShell. vi and edit commands hang.

emacs produces the error message "standard input is not a tty".

To solve this issue, Jered suggests copying the file locally to edit it. Here's an improved version of their answer that uses pssessions instead of UNC:

PS C:\Users\Meredith> Invoke-Command -Session $ps -ScriptBlock {get-content c:/inetpub/myapp/web.config} > web.config

Edit the web.config file

PS C:\Users\Meredith> get-content web.config | Invoke-Command -Session $ps -ScriptBlock {set-content c:/inetpub/myapp/web.config}

The Invoke-Commands can be run in either direction, from local to remote or remote to local.


这并不回答如何方便地编辑文件,而是对挂起行为的解释,因此我将其发布为评论。您的会话似乎挂起,因为远程会话不会为您虚拟窗口化应用程序;也就是说,如果您通过终端服务连接,则可以在远程桌面中看到您的编辑会话。 - kbrimington
它也不太适用于交互式控制台应用程序。 - x0n
10个回答

28

如果您正在使用PowerShell 5,可以使用名为PSEdit的命令进行编辑。它只能从ISE中工作。

  1. 首先,打开PowerShell ISE
  2. 然后使用Enter-PSSession打开到远程计算机的远程会话
  3. 然后使用PsEdit 'filename'编辑文件

远程文件将在本地ISE窗口的新选项卡中打开。

实际上,我从这个SO问题的评论部分找到了这个答案,但我认为如果我在这里发布它作为答案,对其他人也会有帮助。


4

首先,在本地机器上创建一个临时文件夹(LOCALTEMPFOLDER)。然后使用以下函数:

function vimrem {param([parameter(position=0,mandatory=$true)][string]$Session, [parameter(position=1,mandatory=$true)][string]$Path)

$TempFile = split-path -path $Path -leaf

copy-item -fromsession $Session -path $Path -destination LOCALTEMPFOLDER\$TempFile

vim $LOCALTEMPFOLDER\$TempFile

copy-item -tosession $Session -path LOCALTEMPFOLDER\$TempFile -destination $Path

remove-item -path LOCALTEMPFOLDER\$TempFile

}

这应该有效,但在使用此功能之前,您必须退出交互式会话。


1
你不需要在回答前列举示例问题,只需回答并附上任何解释即可。 - AfroThundr

4

你能不能先把文件拉到本地,编辑完后再上传呢?我知道这很繁琐也不够优雅,但是目前看来编辑器在远程会话上存在问题。

例如:

Get-Content REMOTE\Filename.txt > LOCAL\Filename.txt

在本地进行更改,然后

Set-Content -path REMOTE\Filename.txt -value (get-content LOCAL\Filename.txt)

编辑

如果你只是要替换某些部分,那么这个操作非常简单。

例如:

Get-Content REMOTE\Filename.txt | foreach-object { $_ -replace "OLD", "NEW" } | Set-Content REMOTE\Filename.txt

一个很好的替代方案,可以取代我最初的想法——在远程共享上打开本地编辑器。但是这个方案通过将文件复制到本地共享,再使用本地编辑器,最后再将文件复制回原始位置,来颠倒依赖关系。我真的很想摆脱对文件共享的依赖,这样我就可以只暴露winrm而不是任何其他服务。 - guutlee
你正在进行哪种类型的编辑?它是否遵循一个模式? - Jered Odegard
我猜大部分都是临时性的工作,比如向HTML文件中添加一段文本;更新Web应用程序中的连接字符串;修改PowerShell脚本以添加某些功能。 - guutlee
只有在将 Get-Content 放在括号中以确保文件在写入时不被打开时,EDIT 才能正常工作。请参阅帮助(示例 3)Technet Set-Content - fadanner

4

经过大量搜索,我在powershell帮助文档中找到了一些相关的内容。在powershell提示符下,输入:

help about_remote_troubleshooting

在显示的帮助文件的最后,有一个名为“TROUBLESHOOTING UNRESPONSIVE BEHAVIOUR”的部分,其中写道:

故障排除不响应的行为

本节讨论远程问题,可能会阻止命令完成并阻止或延迟返回Windows PowerShell提示符。

如何中断命令


某些原生的Windows程序(例如具有用户界面的程序、提示输入的控制台应用程序以及使用Win32控制台API的控制台应用程序)在Windows PowerShell远程主机中无法正常工作。

当您使用这些程序时,可能会看到意外的行为,例如没有输出、部分输出或未能完成的远程命令。要结束无响应的程序,请输入CTRL + C。要查看可能报告的任何错误,请在本地主机和远程会话中键入"$error"。

因此,即使是非GUI控制台应用程序,如VIM,也不幸无法使用。是否有人愿意解释一下为什么会这样,或者是否可以解决这个问题?我真的很想在powershell remoting上使用vim。


3
我可以解释一下为什么:在Windows上的控制台IO更像是对设备进行ioctls(带外信号)而不是流式控制码。请查看API结构,网址为http://msdn.microsoft.com/en-us/library/windows/desktop/ms682088%28v=vs.85%29.aspx。与此相比,例如VT100仿真的工作方式(嵌入式逃逸序列带内)。PowerShell基于流式I/O操作,而不是基于控制台。 - user314104

4
PowerShell_ISE.exe \\REMOTE\...\File.txt 

这个工具可以直接加载和编辑文件,并在一步中将其保存回远程计算机,由于是命令行方式,因此使用它很容易构建功能。虽然无法解决共享问题,但这是我发现的最简单的方法。


1

我尝试了以上所有建议,甚至其他与微软相关的解决方案,但都不能像你和我想要的那样实现“完全交互和响应式的shell”。如果你真的想要拥有类Unix用户从一开始就拥有的ssh体验,我建议你安装一个ssh服务器。我个人使用freesshd,你可以在这里找到它 http://www.freesshd.com,以及如何配置它的说明在这里 http://www.windowsnetworking.com/articles_tutorials/install-SSH-Server-Windows-Server-2008.html。在按照说明进行所有操作后,你只需要使用任何ssh客户端应用程序连接到你的计算机并使用powershell进行完全交互即可。Vim、edit、emacs或者你用来编辑文件的任何工具都将毫无问题地运行。

我鼓励你不要浪费时间去尝试psremoting、telnet、winrs、psexec等方法来实现真正的交互式shell(我已经失去了它,T_T)。尝试一下ssh服务器,亲自体验一下吧。


PowerShell 会话旨在无状态,它们从未被设计成“完全交互和响应式 shell”。*nix shells 和 PowerShell 都有优点,而这恰好是其中之一的劣势。尽管如此,已经有一些很好的建议可以解决这个问题。 - Shafiq Jetha

1

尝试使用基于控制台的编辑器,如VI或Emacs进行测试。正如我的评论所述,我认为问题在于编辑命令绑定到了一个窗口化应用程序,而该应用程序又无法在远程会话中进行虚拟化。


我认为edit.com是控制台编辑器而不是窗口应用程序。我安装了emacs,(好吧,我已经安装了emacs,试图用powershell摆脱我的UNIX根源 :))。这是输出:
[appprod]:PS C:\emacs-23.2> .\bin\emacs.exe -nw .\README.W32 emacs.exe:emacs:标准输入不是tty + CategoryInfo : NotSpecified: (emacs: standard input is not a tty:String) [ ], RemoteException
  • FullyQualifiedErrorId : NativeCommandError
- guutlee
糟糕。VI 有用吗?我可以从远程会话中运行 cmd,所以我可能过于乐观地认为其他控制台应用程序也会起作用。 - kbrimington
我从远程会话中运行了cmd,它运行了,但立即返回到powershell。你看到的是不同的行为吗?我尝试了vi,它像edit一样挂起了。我的测试如上所述。 - guutlee
我相当确定,但我应该回到办公室检查一下。我似乎记得在控制我的SharePoint服务器时在远程会话中使用cmd。 - kbrimington
顺便提一下,您可以很可能依靠 c$ 共享可访问性,因为它仅对管理员开放,并且您必须是管理员才能使用远程操作。这并不能解决通过远程会话编辑的问题,但也许它会增强您在本地会话中使用编辑器的信心。 - kbrimington
也许现在我的服务器只能通过终端服务远程访问,我不允许远程文件共享。我想使用PowerShell或WinRM来代替终端服务。 - guutlee

1

受 @chenz 提供的答案启发,当在 Powershell 集成式 Shell 中时,也可以使用 Visual Studio Code 进行操作。我尝试了在 SSH 远程连接上使用 Powershell 7 进行操作,但也应该适用于 WinRM 远程连接。

Enter-Session ...
[RemoteSystem] PS> psedit service.log

文件名将遵循此模式:

C:\users\dev\appdata\local\temp\2\pses-15960\remotefiles\1702137071\winboxname\service.log


psedit不被识别为有效的cmdlet、函数等。 有其他方法吗? - Raul Chiarella
@RaulChiarella 你在使用Visual Studio Code编辑器吗? - craigdfrench

0

鉴于PSRemoting的限制和可能的解决方法,我已经深入研究了这个问题。

控制台编辑器不起作用,因为它们是本地(exe)命令并且基于字符。 (我想知道ssh上的cmd是否与这些一起工作)。 它需要成为一个cmdlet才能正确地与psremote会话中的控制台主机交互。

PSRemote会话是基于行的。 您在本地编辑该行,按Enter然后将其发送到远程端口,执行命令并返回结果。 因此,它支持行交互但不支持字符交互。

考虑到所有这些限制,GNU的ed似乎是完美的选择。 我很惊讶没有人考虑将其实现为cmdlet。

我决定进一步调查,检查powershell cmdlet read-host是否有效,然后检查C#等效项PSHostUserInterface.ReadLine()是否在PSRemote会话上工作,它们确实可以,这就是制作工作行编辑器所需的全部内容。

因此,这是我迄今为止所做的。 对于更奇特的正则表达式代码,我可能需要一些帮助。

https://github.com/silicontrip/ps-ed

我曾经使用它通过psremote会话编辑文件。(我不会用它来编辑大型源文件,但对于偶尔的小配置文件或ps1脚本来说,它是完美的。)

在使用此cmdlet之前,请确保您熟悉GNU ED。否则就像第一次尝试使用VI一样。


0

我很容易地通过SSH到PowerShell上使nano工作。它在Chocolatey中可用,所以你只需要...

choco install nano -y

然后你就可以这样做...

nano filename

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