因为 Linux 用习惯了,没有 su/sudo命令总觉得不太方便,经过一番搜索,决定自己来实现一个 su 命令。
基本思路是:
- 通过别名来调用一个自定义函数(函数可以写在类似于 .bashrc 这样的文件里)
- 函数要能提权(不需要绕过UAC)
实现
那么我们先确定 .bashrc 类似的配置文件的位置。
> Get-Variable PROFILE
Name Value
---- -----
PROFILE C:\Users\Yourname\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
然后用编辑器(如 Notepad++ 或 Notepad2)打开这个文件,在里面输入如下内容:
function su-fun {Start-Process powershell -Verb runAs -argumentlist '-NoExit', "cd '$pwd'"}
set-alias su su-fun
set-alias sudo su-fun
保存即可。
解析:
首先我们看这一句
Start-Process powershell -Verb runAs -argumentlist '-NoExit', "cd '$pwd'"
前半段很好理解,Start-Process powershell -Verb runAs
就是新建一个 Powershell 窗口,后面的 -verb runAs
就是 “Run as Administrator 的意思,也就是以管理员身份启动一个新的 Powershell 窗口。
后半段是什么意思呢?细心的人会发现,通过之前那句命令启动的 shell 的工作目录是在默认工作目录,也就是C:\Windows\System32
,而不是我们之前的位置。那么我们怎么样吧工作目录传递过去呢?
首先我想到的是 start-process
的 -WorkingDirectory <String>
参数,但是实际测试发现不管用,应该是安全起见,RunAs 和 WorkingDirectory 不能同时启用,请参见 Stack Overflow
In practice, as of PSv5 – and the docs do not mention that – the -WorkingDirectory parameter is not respected if you start a process elevated (with administrative privileges, which is what -Verb RunAs – somewhat obscurely – does): the location defaults to $env:SYSTEMROOT\system32 (typically, C:\Windows\System32)
与此同时,该贴答主还贴出了解决方案
Start-Process -FilePath powershell.exe -Verb Runas -ArgumentList '-NoExit', '-Command', 'cd C:\ws'
也就是说,把 cd xxx
作为一个命令传入新开的 Powershell 中。
但我们不能照搬嘛,我们要把 C:\ws
改成我们的当前目录,而在 Powershell 中,存有当前目录的变量就是 $pwd
,于是命令便顺理成章地变成了
Start-Process -FilePath powershell.exe -Verb Runas `
-ArgumentList '-NoExit', '-Command', "cd '$pwd'"
$pwd
外加上了引号,避免路径中包含空格时出问题
命令有了,怎么让这个命令拥有别名呢?当然,我们可以把这个命令保存为批处理脚本放到 C:\Windows\System32
,但这样毕竟不优雅,有没有不用脚本也能达到相同效果的呢?我首先想到的就是 Set-Alias
这个命令,Alias 就是别名的意思嘛。但是 Set-Alias
不能设置这么长的命令的别名,怎么办呢?
又是一番搜索,找到了这个How to create a complex powershell alias
里面提到,可以先用 function 把要执行的代码块包起来,然后给这个 function 一个别名。
于是整体思路就出来了:在配置文档里面用 function 创建代码块,并且给它一个别名。
function sudo-fun {Start-Process powershell -Verb runAs -argumentlist '-NoExit', "cd '$pwd'"}
set-alias sudo sudo-fun
DEBUG
若出现如图所示错误,是因为你的系统为了自保护,默认禁用了ps脚本(也就是我们的配置文件)的执行,我们需要用管理员身份执行这个命令 Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
来允许它
这样子就可以了
参考文档:Start-Process - Microsoft Docs
EOF