在Microsoft Build 2019上微软发布了Windows Terminal,在2019年6月中旬,微软正式在应用商店上架了Windows Terminal的Preview版本,趁此机会配置一下Windows下的终端和shell
终端与Shell
这里需要了解一下终端 terminal和 shell 的区别: 在命令行中,shell 提供了访问操作系统内核功能的途径,比如说我们所熟悉的 bash、zsh,都是不同的 shell;而终端则为 shell 提供视觉界面(窗口),比如我们所熟悉的 iTerm2、Linux 桌面上的终端工具等。甚至于我们在 VSCode 中所使用的命令行,也是某种意义上的终端。 我们在 Windows 下所使用的 CMD、Powershell 既然是一个终端,也是一个 Shell,还是同名的脚本系统。
所以Windows Termianl只是一个终端而已,而没有提供一个更加好用的Shell,改善体验的话两个部分都需要配置
对于终端,Windows下最常用的:
- CMD的黑色背景的终端
- Powershell的蓝色背景的终端
- WSL的默认Bash终端
相比于其他“现代终端软件”如Cmder在美观和易用性上都显得非常落后,Cmder是一个Console Emulator,对这个概念个人的理解是这样的:
在图形化界面出现之前,与Unix系统交互的唯一方式就是借助Shell所提供的文本命令行界面(Command Line Interface,CLI),而日常用的操作系统都配备了图形化界面,如一些Linux发行版进入CLI的一种方法是退出图形化界面,进入文本模式,也就是显示器上只有shell CLI,这种方式就叫做Linux控制台(Linux Console),而Linux系统启动后又会创建出多个虚拟控制台(TTY)方便使用;而另外一种方式也就是在图形化界面打开图形化的终端窗口连接到TTY,也就是终端仿真器(Console Emulator)。
Cmder不仅仅解决了Windows下终端的美观性问题还支持部分Linux命令(cmd模式下区分于Powershell自带的别名)使得shell的体验更好
然而cmder并没有真正的集成到系统中去,比如说Git依然需要单独安装,某些命令和cmder内建的指令存在冲突,尽管使用Scoop解决了部分安装软件和配置环境变量的问题,系统自带终端和Shell依然是不好用
因为个人一直觉得能用自带的就不用第三方,所以就往配置方面查了一些东西,发现主要是以下几个问题:
- 终端代码页不支持大部分的字体,如Consola
- 终端的配色、主题自定义相对不便
- Powershell用不习惯
- 缺少顺手的命令行工具
下面就来一个个的解决
修改字体
默认的Powershell终端窗口是无法使用Consola字体的,考虑到偶尔还是要用的,所以可以在运行的时候输入chcp 65001使代码页用UTF8进行编码,而在新版本的Win10中,在“控制面板-时钟和区域-区域-管理-更改系统区域设置”可以打开系统编码默认为UTF8的设置,看了下评论,现阶段还是可能存在一些问题,我暂时没有遇到,另外还有其他的字体可以不依赖于此使用:
Microsoft YaHei Mono on GitHub 微软为 WSL/Bash on Ubuntu on Windows 设计的字体,PowerShell 和 cmd也能用效果相当于微软雅黑和 Consolas 的混搭
更详细的可以参考:自定义 Windows PowerShell 和 cmd 的字体
Pshazz扩展
作者在其Github项目页面:lukesampson/pshazz介绍如下:
给你的powershell一些pizazz,Pshazz扩展了您的Powershell配置文件通过添加:
- 一个更好的提示,包括Git和Mercurial信息
- Git和Mercurial标签完成
- 一个SSH帮助程序,可让您再也不输入私钥密码
- 明智的别名,以及添加自己的别名和删除不喜欢的别名的简单方法
主要还是主题,可以在~\scoop\apps\pshazz\current\themes
目录下修改或者创建主题配置文件,下面是参考自带主题和Wiki修改的,添加了Conda环境的显示(使用文末的方法添加的Conda环境变量),pshazz use THEME_NAME.json
即可应用主题
{
"plugins": [ "git", "ssh", "z", "virtualenv" ],
"prompt": [
[ "green", "", " $path" ],
[ "white", "", "$(if ($git_branch) {' on git:'} else {':'})" ],
[ "cyan", "", "$git_branch" ],
[ "red", "", " $git_local_state" ],
[ "white", "", " $git_remote_state" ],
[ "", "", " [$([datetime]::now.tostring(\"HH:mm:ss\"))]" ],
[ "darkgreen", "", " $Env:CONDA_DEFAULT_ENV "],
[ "white", "", "`n`$" ]
],
"git": {
"prompt_unstaged": "*",
"prompt_staged": "+",
"prompt_stash": "$",
"prompt_untracked": "%",
"prompt_remote_push": ">",
"prompt_remote_pull": "<",
"prompt_remote_same": "="
}
}
这个作者同时也开发了Windows下的包管理软件scoop,在我之前的文章中有介绍,网上搜一下也有其他人写的配置文章;另外一个就是自定义配色的问题了,依然使用这个作者开发的工具
Concfg修改配色
先贴上Github项目链接:lukesampson/concfg
concfg 是一个实用程序,用于导入和导出Windows控制台设置,如字体和颜色,这里主要是更改一下颜色的映射关系,因为最后呈现的效果也取决于终端,所以还是时不时还是需要细调(建议给编辑器装些色彩方面的插件),配置文件路径~\scoop\apps\concfg\current\presets
{
"cursor_size": "small",
"command_history_length": 50,
"num_history_buffers": 4,
"command_history_no_duplication": false,
"quick_edit": true,
"insert_mode": true,
"load_console_IME": true,
"font_face": "Consolas",
"font_true_type": true,
"font_size": "0x18",
"font_weight": 0,
"screen_buffer_size": "80x3000",
"window_size": "80x20",
"fullscreen": false,
"popup_colors": "cyan,white",
"screen_colors": "white,black",
"black": "#1E1E1E",
"dark_blue": "#2472C8",
"dark_green": "#0DBC79",
"dark_cyan": "#11A8CD",
"dark_red": "#CD3131",
"dark_magenta": "#BC3FBC",
"dark_yellow": "#E5E510",
"gray": "#E5E5E5",
"dark_gray": "#666666",
"blue": "#3B8EEA",
"green": "#23D18B",
"cyan": "#29B8DB",
"red": "#F14C4C",
"magenta": "#D670D6",
"yellow": "#F5F543",
"white": "#E5E5E5"
}
Windows Terminal
首先需要注意的现在还是pre-realses状态的软件,可靠性不好说(偶尔比较稳,偶尔复制个文本就闪退了,10月之后还可以,因为自动更新的存在,稳定性随缘),不推荐作为处理重要任务的工具;本文会更新的Windows Terminal的部分动态和配置文件以方便上手
动态
每次大版本更新的feature可以参考开发博客,下面罗列下历史(之前截的图)
- Microsoft Build 2019期间发布,Github开源Introducing Windows Terminal,可以自行编译使用(默认设置和宣传图相差甚远,所以就有了这篇文章)
▲发布后的第一个版本的默认的设置(1903的浅色模式下) ▲修改设置后 ▲宣传图
- 在2019年6月中旬,微软正式在应用商店上架了Windows Terminal的Preview版本,现阶段只有Json的方式做配置(看VSCode的情况,基本上一直只有Json了)
- 九月份以来的0.4.2382.0版本的稳定性堪忧,日常奔溃,经常需要电脑重启才可以解决(可能杀掉后台进程就好了吧)
- 九月底,Windows Terminal迎来大更新,导致本文之前的配置文件的格式变得不可用,0.5.2661.0的Release Note写到:
There’s a settings schema! If you’re using VS Code, it can help you not write typos. (#2803) 也就是说使用VSCode才能获得设置的提示,这点和VSCode的JSON配置方式是一样的,在填写JSON的时候有提示和默认值
- 11月底,迎来了0.7更新,带来了分屏(之前的DEMO用的tmux),可拖动的标签,更美观的边框(窄边框),终端内默认支持中文输入
边框问题在Github上早就有issue了,之前不得不使用深色的背景和较低的透明度来掩盖这个问题,对比如下
需要在系统设置的个性化中开启“标题栏和窗口边框”(如果不开启就默认为白色)
至于分屏,很多终端软件都有,添加分屏窗口时打开的是默认的shell
The following key bindings are included by default within this release to invoke panes actions:
{ "command": "splitHorizontal", "keys": [ "alt+shift+-" ] }, { "command": "splitVertical", "keys": [ "alt+shift+plus" ] }, { "command": { "action": "moveFocus", "direction":"down" }, "keys": [ "alt+down" ] }, { "command": { "action": "moveFocus", "direction":"left" }, "keys": [ "alt+left" ] }, { "command": { "action": "moveFocus", "direction":"right" }, "keys": [ "alt+right" ] }, { "command": { "action": "moveFocus", "direction":"up" }, "keys": [ "alt+up" ] }, { "command": { "action": "resizePane", "direction":"down" }, "keys": [ "alt+shift+down" ] }, { "command": { "action": "resizePane", "direction":"left" }, "keys": [ "alt+shift+left" ] }, { "command": { "action": "resizePane", "direction":"right" }, "keys": [ "alt+shift+right" ] }, { "command": { "action": "resizePane", "direction":"up" }, "keys": [ "alt+shift+up" ] },
我也不清楚编译菜单的横纹是是什么情况…
安装
仅支持1903以上的Win10,主要的安装方式是微软的应用商店(方便自动更新),如果搜索不到的话需要把地区更改为中国以外的地区(如美国,同时也会发现Win10多了很多东西)再搜索
还可以到Github的Realses Page下载安装包
另外在Scoop的dorado仓库中做了收录,添加仓库后安装即可(方法见后文)
Profile参考
具体的配置选项可以参考Github仓库下的文档:Profiles.json Documentation
0.5.2661.0版本更新之后,之前默认的配色方案和快捷键不再出现在主配置文件中,profile文件负责自定义标签,配色和快捷键,更新之后把之前自定义的部分复制过来就好,就默认的配置文件来说,需要调节的部分不多即可达到最初的宣传图的效果,考虑到刚刚上手配置起来有些繁琐,可以参考之前的配置做些必要的修改:
\\开启背景透明(亚克力透明)
"useAcrylic" : true
\\透明度
"acrylicOpacity" : 0.75
\\背景图片
"backgroundImage": "PATH_TO_IMG"
\\配色方案,内置了One Half Dark/Light、Campell、Solarize
"colorScheme": "One Half Dark"
\\图标
"icon" : "C:\\Users\\lwz32\\Pictures\\openwrt.ico",
另外修改启动目录时(比如设定为wsl的~),如果使用wsl -d debian
会无效,直接使用debian
即可,参考自Windows Terminal 的 WSL 配置
除了常见的命令行环境还有其他的工具也可以使用,只需要修改json中的commandline项为需要运行的命令即可(guid不能出现重复,稍微修改下就好)
便捷地使用SSH
在版本较新的Windows 10中已经内置了OpenSSH,可以用SSH和SCP,如果搭配上私钥登陆认证以及Terminal添加新建窗口的自定义命令,可以免去平时一些繁琐的SSH操作
生成密钥,默认暂时是RSA-2048bit
ssh-keygen
之后会提示输入密钥的保存路径,如果是初次设置默认就好,否则会覆盖掉之前的文件
~: [00:42:02]
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (C:\Users\USER/.ssh/id_rsa):
完成后会在指定的目录生成指定文件名的两个文件:私钥id_rsa和公钥id_rsa.pub,公钥保存在ssh-server中就好,Ubuntu和Debian默认在/root/.ssh/authorized_keys文件中,把公钥的文件内容复制进去就好
之后在Terminal中添加标签,在profiles下添加一项(主要修改commandline、name,GUID只要不和已有的重复就行):
{
"guid": "{61c54bbd-c2c6-5271-96e7-0f9a87ff44bf}",
"name": "OpenWrt",
"background": "#000000",
"useAcrylic": true,
"acrylicOpacity": 0.7,
"commandline": "ssh root@192.168.1.1",
"colorScheme": "One Half Dark",
"icon" : "C:\\Users\\*\\Pictures\\openwrt.ico",
"fontSize": 11
}
Powershell
偶尔不得不用,如果要常用Powershell处理文件的重定向,强烈建议看下本文后面的一节:Powershell与bash的重定向的差异
获取插件
Powershell Gallery中也有类似的插件,因为体系不同就不详细介绍了
使用Conda环境
cmder这方面做的非常省事,而bash会有conda init,但是Powershell还是需要些额外的工作
Anaconda安装过程中添加环境变量后,Powershell可以运行Conda命令,但是无法激活Conda环境,需要做些额外的工作,参考:BCSharp/PSCondaEnvs,解决Win10 PowerShell无法激活Anaconda环境的问题
对于4.6之后的版本,实践的过程,和第二篇文章有点不一样,依然需要管理员模式下运行三步
conda install -n root -c pscondaenvs pscondaenvs
Set-ExecutionPolicy RemoteSigned
conda init powershell
自带的别名
PowerShell设置命令别名Alias一文中有介绍Powershell的别名设置情况
通过Get-Alias
可以看到其实默认可用的别名和Linux系统差不多了,相对CMD的一大优势,只是支持的Powershell的内建命令
~: [01:12:12]
$ Get-Alias
别名解决了相当一部分的命令的便利性问题,但是有些场景还是有些尴尬的,比如说统计字符数,最短的方式是这样
~: [01:22:58]
$ cat C:\Users\lwz32/.ssh/id_rsa | measure -c -l -w
Lines Words Characters Property
----- ----- ---------- --------
27 33 1648
这个可以使用参考文章中的更改带参数的别名解决,但是还是有些麻烦,还不如直接使用WSL的wc
~: [01:23:35]
$ cat C:\Users\lwz32/.ssh/id_rsa | wsl wc
27 33 1702
如果想要相对自由的设置别名的话可以使用下文中的scoop
Scoop
安装命令行工具
以博客中介绍Scoop的文章为主,这里就摘取和本文主题相关的部分
默认的main仓库以命令行工具为主(比如收录的cmder是个有GUI的终端软件),例如Linux常用的sed, grep, gawk,vim可以大大方便Powershell的日常使用,需要注意的是如果Scoop安装的软件和Powershell的命令或者别名重合,Powershell的命令依然被优先使用(例如wget)
除去上面介绍的一些,其实想得到命令行工具都可以在Scoop中使用scoop search
找下看看
$ scoop list
Installed apps:
7zip 19.00
chromedriver 76.0.3809.126
cmder-full 1.3.11
concfg 0.2019.03.09
ffmpeg 4.1.3 #编码工具
gawk 3.1.7
gcc 8.1.0
gdrive
git 2.21.0.windows.1
grep 2.5.4
innounp 0.48
iperf3 3.1.3 #网速测试工具
nodejs 12.5.0
pshazz 0.2019.04.02
R 3.6.0
sed 4.2.1
tesseract 4.1.0.20190314 #OCR工具
vim 8.1.1302
youtube-dl 2019.05.20 #偶尔下载视频
trafficmonitor #任务栏网速,CPU内存占用监测
screentogif #Gif录屏软件
Scoop别名
Powershell的别名设置不方便,直接使用WSL的自定义别名(.bashrc)调用Windows下的程序又不能直接在Powershell中运行,直到发现Scoop可以自由的添加“环境变量”,想起来Scoop alias来设置程序运行的scoop别名
本来的用法应该是为Scoop内的操作添加别名:
# Install app
scoop alias add i 'scoop install $args[0]' 'Innstall app'
scoop alias add add 'scoop install $args[0]' 'Install app'
# Uninstall app
scoop alias add rm 'scoop uninstall $args[0]' 'Uninstall an app'
scoop alias add remove 'scoop uninstall $args[0]' 'Uninstall an app'
# List apps
scoop alias add ls 'scoop list' 'List installed apps'
# Update
scoop alias add u 'scoop update $args[0]' 'Update apps, or Scoop itself'
scoop alias add upgrade 'scoop update $args[0]' 'Update apps, or Scoop itself'
但是这个格式看起来就很自由:
比如说给WinMTRCmd添加一个scoop mtr
的别名
scoop alias add mtr '~/winMTRCmd $args[0]' 'MTR tools for Win CMD'
之后使用scoop mtr HOSTNAME
就可以愉快的使用mtr工具了
Powershell与bash的重定向的差异
探索这个问题的背景是:XDR6088刷OpenWrt:Powershell下使用nc命令重定向的备份大小异常
在Windows下使用nc导出路由器备份的mtdblock的时候,Windows上一定要用CMD运行nc并重定向(
nc -l -p 9995 > backup.img
),不能用Powershell(备份传输完成后,校验的话就会发现用Powershell运行同样的命令会得到不一样的文件),因为这一条操作失误导致我刷OpenWrt后刷回原厂系统的过程中导致变砖
类似的问题:在Powershell使用docker命令保存镜像,用重定向符有问题,不能直接复制linux bash的命令
问题的简化与复现
可以尝试构建一个二进制文件:原文件.img,用Powershell的重定向输出了一个新文件(参考cat 原文件.img > 新文件.img,对比大小就能发现重定向输出的文件与源文件不一样,这就是要解决的问题:需是在原文件丢失的情况下,使用新文件还原出原文件
如果用cmd执行相同的命令的话就没有这个问题,下面继续探索
对比文件的差异
首先我用16进制的编辑器打开文件,做字段的对比,每一行12个十六进制的pair(这里将形如FF的2个十六进制数的缩写称为1个pair)
FF FE 55 00 42 00 49 00 23 00 01 00
00 00 00 00 00 00 00 00 00 00 00 00 # 12个00
00 00 00 00 00 00 00 00 01 # 8个00
55 42 49 23 01
00 00 00 00 00 00 00 00 00 00 # 10个00,下面一行省略
01
看起来是在每个16进制pair字符后都加了00,这里想起了windows的文件编码差异,即Powershell使用CRLF UTF-16 LE BOM而CMD命令行使用的LF ANSI,通过NotePad++打开,发现新文件是UTF-16 BOM编码的,原文件是ANSI(普通二进制文件),就常规的文本文件而言,解决的办法就是在NotePad++中选择重新编码保存,然而在这个问题上不管用
关于windows下的各种编码,可以参考Unicode 编码及 UTF-32, UTF-16 和 UTF-8
重编码+dos2unix之后,用16进制的编辑器打开文件对比,还是有个别位的值不一样(最主要的是文件大小都不一样)
编码问题 or Powershell的机制问题
对此也和同学进行了探讨,焦点在于文本编码往往有明确的 二进制 到 字符 的一一映射关系,如果考虑将二进制文件使用文本编码来编解码的话,存在部分二进制没有相应的字符对应
在编码的范围内搜索了很久没有找到答案后,目光转向Powershell本身应该如何避免出现输出非二进制数据的文件How to pipe binary data in PowerShell
找到的解释的比较清楚的一篇文章:PowerShell’s Object Pipeline Corrupts Piped Binary Data,其中关键部分机器翻译如下:
这就是发生的事情。PowerShell 做出一些假设:任何以原始字节形式流入的内容都被假定为文本,通过分割表示文本文件中行尾的字节,将文本转换为数组。 文本由输出文件使用标准 Windows 行尾字符重新构成。 虽然这适用于任何类型的文本,但实际上肯定会损坏任何二进制数据。使用默认的文本编码,您还会获得双倍的原始字节和一堆新的 0x0D 字节。当数据被分割成字符串数组时,损坏就会发生。在管道末尾使用二进制编码器不会正确地将数据放回,因为它总是将 CRLF 放在每个数组元素的末尾。不幸的是,由于有不止一种可能的行尾序列,所以这已经是最好的了。使用 Windows 到 Unix 转换不会修复该文件。没有办法把矮矮胖子重新组合起来。
不幸的是,由于有不止一种可能的行尾序列,所以这已经是最好的了。使用 Windows 到 Unix 转换不会修复该文件