原文来自美国 WIRED 的「DR. ELON & MR. MUSK: LIFE INSIDE TESLA’S PRODUCTION HELL」,由阮一峰翻译。
1、
1971年,马斯克出生在南非首都比勒陀利亚的一个白人家庭。母亲是加拿大人,所以他有资格申请加拿大护照。高中一毕业,他就去了加拿大。
他的最终目标是美国。在加拿大待了两年以后,1992年,他终于申请到了宾夕法尼亚大学,在那里拿了经济学本科学位,还有一个物理学的第二学位。
1995年,大学毕业后,他本想接着深造,前往加州的斯坦福大学攻读物理学博士学位。但是,入学两天就退学了。他发现,自己对学术没兴趣。
退学以后,他与朋友一起创业,为报纸开发互联网页面,共有160多家报纸成为了他们的客户,其中包括《纽约时报》这样的全国性大报。1999年,互联网泡沫的最高潮时期,他们的公司被康柏电脑以3.4亿美元收购。马斯克占7%的股份,拿到了2200万美元。
他拿这笔钱,又跟他人一起创办了 PayPal。2002年,eBay 以15亿美元的价格收购了 PayPal。马斯克占 11.7% 的股份,拿到了1.65亿美元。
31岁时,他已经从一个穷光蛋变成了亿万富翁。
2、
发财以后,马斯克过上了奢侈的生活。但是他很快发现,比起驾驶豪华跑车,他还是更喜欢创业,做一些别人没有做过的事情。于是,在很短的一段时间内,他创办或收购了好几家看上去有点疯狂的公司:火箭公司 SpaceX、太阳能公司 Solar City、高速隧道公司 Boring Co.等等。
2004年,电动汽车公司特斯拉寻找外部投资者。那时,特斯拉还是一家小公司,只有几十个人,也没有任何产品。但是,马斯克一眼就看中了它,投了630万美元,成为该公司的最大股东,当上了董事长。后来,他觉得董事长还不过瘾,亲自下场,把创始人赶走,自己变成首席执行官和产品架构师。
2006年,他在一份文件写道:”特斯拉汽车公司的首要目标,也是我为公司提供资金的原因,就是加快让世界从化石能源转向太阳能。……我们不会停下来,直到路上的每辆车都是电动的。”
马斯克的个性在特斯拉汽车上面得到了充分体现。他坚持己见,要求完美,以非传统的方式思考,提出一些别人觉得匪夷所思的要求。他相信,只要能够简化为合乎逻辑的步骤,不可能的事情就会变成可能。
一个典型的例子就是特斯拉汽车的门把手。马斯克坚持认为,把手可以与车身在一个平面上,当用户要开门的时候,把手会像魔术一样滑出来。工程师一致认为,这个想法很疯狂,会带来复杂的设计,而且不必要。但无论别人多么强烈反对,马斯克都不屈服。最终,这个门把手成为了特斯拉汽车的标志,让用户一接触就觉得,这种汽车很人性化,是未来世界的一部分。
这就是马斯克,他想要实现不可能的事情。
3、
2008年,特斯拉推出第一款产品,电动跑车 Roadster。这是世界上第一辆公开发售的锂电池汽车,也是第一辆可以跑300公里的电动汽车。但是,卖得并不好,四年里面一共只卖出了2000多辆。
由于产品不成功,特斯拉公司面临资金枯竭,但是这辆车吸引了很多人的注意,谷歌创始人谢尔盖布林和拉里佩奇、奔驰、丰田、美国能源部都有意投资。特斯拉靠着这些钱,终于渡过难关。
2012年6月,特斯拉推出豪华型的电动车 Model S,续航里程提高到了500公里以上,使得电动车具有了汽油车一样的实用性。这个车型大获成功,立即成为全球最畅销的电动车。
2015年,特斯拉推出电动 SUV 车型 Model X,它的车门会像猎鹰一样向上折叠。这个车型也非常成功。
2016年,特斯拉公司的收入飙升至70亿美元,员工人数已增至18,000人。
4、
随着特斯拉的汽车越来越受欢迎,马斯克也变成了知名人士,像好莱坞明星一样开始登上娱乐版。比如,他花了7200万美元,在一个豪华小区购买了五套豪宅,装潢成不一样的风格,供自己使用。他还公开发表一些奇特的言论,比如在推特上说:”有谣言说,我正在建造一艘飞船,返回我的家乡火星,这并非完全不实。”
(上图画圈的地方,都是马斯克的豪宅。)
他也非常情绪化,会因为没有达到目标而大骂员工。一位离职的高管说,”跟马斯克一起开会的时候,你坐在座位上,身体最好往下蹲一点。因为当马斯克坐得比你高的时候,他会待人友好一些。”不过,在硅谷,各种奇怪的行为都是允许的。而且,如果你是一个奇怪的人,在这里会更受欢迎。
2016年3月,马斯克宣布了一个新车型 Model 3,这是一辆中等价位的电动汽车,瞄准大众市场。售价预估在35,000美元左右,比 Model S 便宜一半还多。特斯拉公司希望以此证明,大规模生产电动汽车是可行的,彻底改变内燃机引擎主导的汽车工业。
当时,Model 3 还处于设计阶段,用户可以付1000美元预订,交车至少要在18个月以后。在特斯拉内部,乐观的估计是预订量会超过50,000辆,这已经接近美国汽车业的纪录。
2016年3月31日,星期五,Model 3 开放预订的第一天,用户可以到当地的特斯拉专卖店交订金。结果,有的地方一早就有超过2000人排队,当天全美的预订量就超过18万辆。等到周末结束,已有32.5万人预订了 Model 3。
特斯拉的股价开始飙升。那时它一共只生产了不到15万辆车,市值就已经超过通用汽车(每周就能生产15万辆车),成为美国市值最高的汽车公司。但是,特斯拉的很多高管都忧心忡忡,因为这么高的预订量意味着,特斯拉必须在很短的时间内(一两年),从一家小型汽车制造公司转变为大规模的汽车生产商,招募并培训数万名员工,有效地管理他们。这对公司的内部管理将是巨大挑战。
5、
马斯克原计划,2017年10月开始生产 Model 3,先是小批量生产,然后在较短的时期内上升到每周生产5000辆。
但是,2016年夏天,他改变了主意,想在2017年7月就开始生产,比计划提前近四个月。他还想建一个全自动化的工厂,机器人在流水线上高速地建造一切东西,传送带将每件零件及时送到正确的地方。为了达到这个目标,马斯克说,各部门都需要重新安排他们的计划,改变流水线的设计。
高管们告诉马斯克,这是不切实际的,特斯拉已经是最先进的汽车制造工厂,可以渐进式地改造,在生产运行顺利以后,逐步增加自动化程度。这么短的时间内,重新规划流水线,设计一个全新的自动化工厂将耗费大量时间和金钱,而且不一定能够达到目标。但是,马斯克坚持认为,除非违反物理定律,否则几乎任何事情都是可能的。他对高官说,”我们将构建能够构建机器的机器,而且必须快速行动。一家全自动化工厂是对特斯拉未来的投资,将有助于公司在未来几十年保持竞争力。”
接下来的几周里,高管不断与马斯克争论,工程师也提出质疑。遇到这种情况,马斯克有时会将该人的主管拉到一边,让他将该人分配到其他岗位,或者马斯克索性不再邀请质疑者参加会议,甚至直接将他解雇。
这个时期,马斯克解雇了很多人。一位前员工说,”每个人每天来上班的时候,都不知道这是否会成为他们在特斯拉的最后一天。马斯克说过,特斯拉的目标是拯救世界,与这个目标相比,个人的感受有什么重要呢。他关心的是整个人类,并不真正关心个人。”
马斯克后来估计,为了工厂改造,特斯拉每周要花费1亿美元。
6、
2017年夏天,原定的投产日期已经到了,但是 Model 3 仍然没有批量生产。工程师们仍在解决一些棘手的问题,比如让机器人识别并可靠地抓住不同颜色的电线,以及通过迷宫一样的传送带,将零件送到需要的地方。
由于远远落后于时间表,一些客户开始要求取回订金。为了平息外界的质疑,马斯克决定,7月28日召开一场 Model 3 的大型新闻发布会。特斯拉从来不在广告上花钱,而是通过发布会这种场合,产生大量的新闻报道和网络转发,以帮助销售汽车。发布会上,马斯克向前30名 Model 3 的预订者(大多数都是特斯拉的员工),交付了汽车。由于装配线还没好,这些车每一辆都是单独制造的。
就算到了这种时候,马斯克依然不改随便说话的脾气。那个月早些时候,他发了一条推特,声称特斯拉将在年底前每个月生产2万辆汽车。他希望通过发布会和媒体宣传,消费者可以继续对 Model 3 保持耐心。
一名前高级主管说,”马斯克是一个疯狂的天才。他的个性里面,95%是天才和5%是疯狂。但是,从那个时候开始,可能因为 Model 3 的压力,这个比例颠倒过来了,变成95%是疯狂和5%是天才。”
7、
2017年10月,Model 3 的生产远远落后于计划。目标是每周建造5,000辆汽车,但是实际上每天只能生产大约三辆汽车。
(上图为特斯拉在内华达州的工厂,目前世界最先进的汽车工厂。整个厂房就在一个大屋顶下面,屋顶上都是太阳能电池。)
马斯克坐不住了,整个周末都待在工厂,试图发现为什么机器不能正常工作。他的目标是工厂尽可能自动化,但是这种极端的机器人化,带来的后果是延迟和故障。特斯拉已经花费超过10亿美元建造自动化工厂,但是现在工厂几乎没有办法正常运行。
他视察生产线,如果发现问题,就找来负责的工人,为他为什么自动化没起作用。工人没有想到,能够直接跟老板对话,涨红了脸,回答支支吾吾。马斯克大发雷霆,告诉工人,在特斯拉,卓越只是基本的要求,现在你失败了,你不够聪明,不能解决这些问题,正在危害公司。他当场就把工人解雇了。
高管把马斯克拉进会议室,跟他说:”有一句谚语,被老虎追赶时,没有人能想出一个好主意。”但是,马斯克坚持自己的做法,最终解雇了700多人。他不担心招聘,因为有很多合格的人想在特斯拉工作。”这是真正改变世界的为数不多的公司之一,”一位前员工表示。
在特斯拉,所有人都知道,马斯克是领导者,最大的股东,也很有远见。有时,他会发表不切实际的长篇大论,但是你只要说错一句话,或者犯了一个错误,他就会认定你是一个白痴,而且没有什么可以改变他的想法。马斯克在会议上公开嘲笑员工,侮辱他们的能力,欺负那些未达表现的人,这是家常便饭。由于压力过大,两年内共有36位副总裁级别以上的高管离职,只有少数高管没有被替换。
不管怎么样,Model 3 装配线总算能够运行了,生产量开始上升,但是距离每周5000辆的目标,还是有很大距离。有人已经起诉特斯拉,美国司法部也开始调查,特斯拉是否故意发布错误的 Model 3 产量预测,误导投资者。
根据公司的季报,2017年的第三季度,特斯拉亏损6.71亿美元,前9个月共亏损15亿美元,仅建造了222辆 Model 3。
8、
2018年4月,马斯克公开承认,全自动化工厂的目标没有实现。为了顺利运行,工人们实际上停止了传送带,人工把汽车零件运送到需要它们的地方。当月,生产线停工一周,进行维修。
由于 Model 3 的生产太不顺利,马斯克似乎有些失控了,推特的发送频率大大加快。2016年和2017年,他每月发推特94条,但在2018年5月,他发了421条,6月414条,7月310条。推特的内容完全无拘无束,跟提出质疑的人在推特上对骂,骂对方是白痴。有一次,他甚至上传了一张日本漫画,下面写着”我实际上就是猫女,这是我的自拍”,推特关闭了他的帐户,因为怀疑被黑客入侵了,直到马斯克确认这确实是他发的。
2018年6月的股东大会上,马斯克说,这是他经历过的最痛苦、最恐怖的几个月。特斯拉的财务报告显示,20%的 Model 3 预订者要求退款。
马斯克开始睡到了工厂,直接解决生产中遇到的各种问题。
2018年8月,也许是因为受够了外界的质疑,马斯克发了一条推特,表示考虑将特斯拉私有化,不再作为上市公司了。特斯拉的股票价格立刻飙升。事后证明,他只是随口一说,完全没有这回事。美国证券交易委员会对马斯克罚款2000万美元,并且要求他辞去董事长职务,但他仍然是首席执行官。
2018年9月,在一个网络直播节目里面,马斯克当众吸食了大麻。虽然大麻在加州是合法的,但马斯克的另一家公司 SpaceX 是美国国防部的承包商,根据国防部的规定,承包商不得与毒品相关。美国宇航局宣布将对 SpaceX 进行评估,确保符合无毒品的要求。
9、
2018年7月1日,在 Model 3 开放预订两年多以后,马斯克终于向全体员工,发送了一封期待已久的电子邮件。
“我认为我们刚刚成为了一家真正的汽车公司。我们在七天内制造了5,031辆 Model 3。”
2018年10月,特斯拉宣布,2018年第三季度实现销售收入61亿美元,净利润3.12亿美元,远远超出华尔街的预期。
董事会也已经同意,未来10年内将向马斯克提供550亿美元的奖金,前提是马斯克继续领导公司,并且达到董事会设定的12个目标。其中有一个目标是市值达到6500亿美元,大约是现在的10倍。如果达不到目标,他就拿不到这笔奖金。
马斯克现在的身价已经超过200亿美元,是世界上最富有的人之一。但是,董事会愿意再给他550亿美元,确保他不离开特斯拉。
]]>当单向链表中存在环的时候,遍历此链表会发生无限循环,无法到达末尾(入环后链表就不存在末尾了)的情况,所以在可能发生这种情况的时候,需要检查链表中是否存在一个环。
检查是链表是否存在环的方法就是「龟兔赛跑」法:乌龟和兔子同时从头节点开始遍历链表,兔子遍历的速度大于乌龟的速度,如果链表中存在环,兔子和乌龟就会先后进环,由于兔子的速度比乌龟快,他们必然会在环内相遇。
下面的动图解释了这一过程:
这个算法的美妙之处在于,乌龟和兔子相遇的地方和环入口点的位置是有关系的。
根据动画所示,我们令兔子的遍历速度为2,乌龟的遍历速度为1,则他们的速度差也为1。设乌龟进环的时候已经遍历了 个节点,那么此时兔子也已经在环内遍历了 个节点。若令环的大小为 ,兔子和乌龟在环内的遍历就是一次追及问题,兔子需要追上乌龟的距离为 。由于兔子和乌龟的速度差为1,所以追及时间 ,那么乌龟和兔子相遇的点距离环入口也就是 了。此时只需要将兔子放回起点,并把兔子的遍历速度换成1,则乌龟将会和兔子在环入口处再次相遇。
最后附上 Java 算法:
1 | LinkedListNode solve(LinkedListNode head) { |
本文章用于检索在 Linux 系统下如何解决某一个问题,每个问题通常使用一个命令的不同参数或者多个命令的组合方式来实现,命令下方给出了简单的解释。可以通过每一个小标题来寻找自己的需求。
1 | find . -name "*.wav" -print | wc -l |
解析:find .
命令可以循环查找当前目录和子目录的文件,-name
参数用于指定文件 pattern,wc -l
按行统计结果。
1 | ls -l |grep "^-"|wc -l ##统计当前文件夹下文件的个数 |
解析:使用 ls -l
命令用长列表模式查看当前目录的文件(包括目录、设备文件等)R
参数递归子目录,grep
命令过滤内容,^d
是文件夹(目录),^-
是普通文件。
1 | # 查看已开放的 tcp 端口 |
1 | telnet www.google.com 80 |
1 | firewall-cmd --state ##查看防火墙状态,是否是running |
1 | nvidia-smi ##查看 GPU 此时的使用情况 |
1.基本格式
1 | for 变量 in 取值列表 |
还有罕见的写法就是都写作一行里:
1 | for 变量 in 取值列表 ; do 各种操作 ;done |
2.普通枚举
取值列表为空格或回车符分割的字符串
1 | for i in 'apple' 'meat' 'sleep' 'woman' |
3.花括号迭代
{1..100}
{a..z},{A..Z},{Z..A}
{a..A}
计算1加到100的和
1 |
|
花括号的迭代还可以指定指定增量,格式如下:
1 | {首..尾..增量} |
计算一下1到100以内的所有奇数的和:
1 | for i in {1..100..2} |
4.C 风格 for 循环
1 |
|
]]>注意!!!这里的for循环要有两层括号
本手册适用于新创建的 Linux 服务器基本环境初始化,包括连接性能优化、Shell 脚本语言和 Vim 环境优化配置。
其中魔改 BBR 部分视情况开启,如果服务器需要用作高性能网络代理,可以开启提高性能,否则不必开启。BBR 开启只能在安装其他软件之前进行,若之后开启则会令安装的软件失效。
如只需要对服务器环境进行配置,不涉及到网络代理;以及本地环境的初始化配置。可直接跳转到 ¶环境配置:切换 Shell 部分开始。
用来提高 SSH 连接远程服务器的输入延时和移动设备连接的稳定性(除非手动操作,基本不会断开连接),安装完成后,直接使用 mosh
代替 ssh
即可。
1 | sudo add-apt-repository ppa:keithw/mosh-dev |
1 | yum -y install epel-release |
如果在内网无法直接访问yum仓库,可以下面的目录查找mosh及依赖的rpm包
http://dl.fedoraproject.org/pub/epel/7/x86_64/
rpm包是安装首字母分类到各个目录的,例如mosh的rpm包在
http://dl.fedoraproject.org/pub/epel/7/x86_64/m/
安装完成后,可能需要打开防火墙的 60000-61000 UDP 端口供 mosh 使用:
Firewall-cmd:
1 | firewall-cmd --zone=public --add-port=60000-61000/udp --permanent |
iptables:
1 | sudo iptables -I INPUT 1 -p udp --dport 60000:61000 -j ACCEPT |
如果出现语言问题,添加到 bashrc
或者 zshrc
:
1 | export LC_ALL="en_US.UTF-8" |
或者更妥善的解决方法是将本地(Mac)的 Shell 环境改为英文:
1 | export LC_ALL=en_US.UTF-8 |
把默认的 bash 切换为 zsh,使用 oh-my-zsh 框架,并使用 k-zsh 配置。
Oh-My-Zsh is a framework for Zsh, the Z shell.
zsh --version
来确认。zsh 4.3.9
或更高的版本则可以。echo $SHELL
来确认。/bin/zsh
或其他 zsh 路径均可。如果需要的话,依照以下步骤来安装 Zsh:
sudo apt-get install zsh
或者 CentOS 下的 sudo yum update && sudo yum -y install zsh
。zsh --version
来验证安装。 如果结果是 zsh 4.3.9
或更高的版本则可以。chsh -s $(which zsh)
/etc/shells
) 或者你没有权限使用 chsh
,上述命令不会成功。 如果是这种情况的话, 你可以依照这个方案执行。.bash_profile
in your home directory and add these lines: export SHELL=/bin/zsh
exec /bin/zsh -l
.profile
may work as a general solution when default shell is not bash. I’m not sure if .profile
may be called by Zsh as well that it could go redundant but we can do it safely with a simple check:export SHELL=/bin/zsh
[ -z "$ZSH_VERSION" ] && exec /bin/zsh -l
echo $SHELL
来确认, 如果结果是 /bin/zsh
或其他 zsh 路径则安装并切换成功。你可以在终端中通过以下任意一条命令来安装 Oh My Zsh。你可以使用 curl
或者 wget
。
1 | sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/\ |
1 | sh -c "$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)" |
k-zsh 是我配置的一套 Oh My Zsh 设置,包含了常用的插件和更清晰的主题效果。
1 | mv ~/.zshrc ~/.zshrc_bac |
k-zsh 中配置了部分插件需要单独安装一下才能生效:
1 | git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions |
其中常用的插件是 z
,快速跳转到相应目录。还有 x
,快速解压缩文件等。
k-vim for server 是 wklken 配置的 k-vim 的服务器版本,包含了许多简单有用的设置,处于便捷考虑 perfix
按键已经被修改为 ,
键。
1 | mv ~/.vimrc ~/.vimrc_bak |
如果需要安装完整非便携版的 k-vim,请根据 https://github.com/kchen0x/k-vim 进行操作。
确保使用 2.3 以上版本的 tmux: tmux -V
。
1 | mv ~/.tmux.conf ~/.tmux.conf_bak |
安装插件管理
1 | git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm |
安装完成后进入 tmux,使用[prefix]加大写I
重载一次插件即可([prefix]为ctrl+a
)。
【服务端】
1 | wget https://raw.githubusercontent.com/cppla/ServerStatus/master/autodeploy/config.json |
【客户端】
1 | wget --no-check-certificate -qO client-linux.py 'https://raw.githubusercontent.com/cppla/ServerStatus/master/clients/client-linux.py' && nohup python client-linux.py SERVER={$SERVER} USER={$USER} PASSWORD={$PASSWORD} >/dev/null 2>&1 & |
在 官网下载 预编译的二进制包。
安装:
1 | sudo dpkg -i <target.deb> |
启动监控服务:
1 | sudo bmdb webremote |
然后默认可以在 localhost:2605/index.html
访问到数据。
BitMeterOS 提供了3个工具可以使用:
1 | bmclient -h |
同时,可以安装 NetHogs 来观察每个进程的实时网速:
1 | sudo apt install nethogs |
在 Linux 系统下经常要查看各种信息,命令蛮多的,而且又是久不久用一次的那种,记不下来,每回找又麻烦,干脆自己写一份在博客里面,自己找起来也方便。
1 | # uname -a # 查看内核/操作系统/CPU信息 |
1 | # free -m # 查看内存使用量和交换区使用量 |
1 | # mount | column -t # 查看挂接的分区状态 |
1 | # ifconfig # 查看所有网络接口的属性 |
1 | # ps -ef # 查看所有进程 |
1 | # w # 查看活动用户 |
1 | # chkconfig --list # 列出所有系统服务 |
1 | # rpm -qa # 查看所有安装的软件包 |
1 | # cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c |
看到有8个逻辑 CPU, 也知道了 CPU 型号
1 | # cat /proc/cpuinfo | grep physical | uniq -c |
说明实际上是两颗4核的CPU
1 | # getconf LONG_BIT |
说明当前 CPU 运行在 32bit 模式下, 但不代表 CPU 不支持 64bit
1 | # cat /proc/cpuinfo | grep flags | grep ' lm ' | wc -l |
结果大于 0, 说明支持 64bit 计算. lm
指 long mode, 支持 lm
则是 64bit
在 Linux 系统中,特别是没有 GUI 的发行版本里,与进程打交道是一件家常便饭的事情,能不能把进程管理玩溜了,完全可以决定你 Linux 系统的使用体验。今天,我们来看一看常见的进程管理工具和技巧。
ps
命令是 process status 的简称,用于显示当前运行的进程的信息。
在不使用任何标识的情况下,ps
会显示所有被当前用户启动的进程,比如:
1 | $ ps |
其中每一列代表:
PID
:进程的 ID 号TTY
:命令执行时所使用的终端 IDTIME
:进程已经运行的时长CMD
:所执行的命令名称ps
一个十分常见的用法是 ps aux
,可以用来显示系统中运行的所有进程,同时也可以提供更多的信息,比如哪个用户启动了该进程、多少 CPU 和内存被占用了等等。
把 ps aux
和 grep
命令通过管道连接来查找特定的进程也是非常常见的用法,例如如果我们想要看见 SSH 服务 sshd
是否正在运行,我们可以使用下面的命令:
1 | $ ps aux | grep sshd |
...
省略了一些信息来来简化上面的输出,其中应该包含了内存占用、运行时间等等,root
是执行进程的用户,2848
是进程的 ID。
每一个进程都是被别的进程启动的,或者说是复刻(Fork)的。当系统刚刚启动的时候,有一个非常特别的根进程 init
,它就是是直接被操作系统内核启动的。
这样一来,这个系统中运行的所有进程集合就构成了一颗以 init
进程为根节点的进程树,所有的进程都有一个父进程,也有可能有多个子进程。
比方说,每次我们在 bash
命令行提示符下执行一个命令的时候,bash
会复刻一个进的进程来执行这个命令,这时这个进程就变成了 bash
的子进程了。
相似地,当我们看见一个「登录」提示符时,这其实是 login
命令在运行着。如果我们成功的登录了,login
命令会复刻一个新的进程来执行登录用户选择的 shell。
ps
命令展示了一个扁平化的进程列表,但是我们可以使用 pstree
命令来查看树形结构的进程列表,像下面这样:
1 | $ pstree |
我们还可以通过 ps auxf
来查看树形结构的显示,只是效果上可能不那么用户友好罢了。
每一个进程都归属于某个特定的用户,归属于该用户的进程有权限像该用户的直接登录了一样执行所有该用户可以执行的所有命令。
比方说,假如有一个进程归 kchen
用户所有,那么这个进程就可以做所有 kchen
用户能做的事情了:编辑 kchen
用户 home
目录下的文件,启动一个归属于 kchen
用户的新进程,等等。
系统进程比如 init
和 login
归属于 root
用户,而且当一个根进程复刻一个新进程的时候,它可以改变这个子进程的归属。
所以,当我们登录后, login
命令会复刻一个新的进程我运行我们的 shell,但是新的进程是所属于成功登陆的那个用户名的。接下来所有的后续命令都会以该用户的名义执行,所启动的进程都归属于他。
默认情况下,只有 root
进程可以像这样改变归属权。
操作系统内核在初始化进程中所做的最后一件事情就是启动「init system」,也就是执行 /sbin/init
命令。「init system」有很多种,但它们都有相同的职责:
这里的服务涵盖了从 web 服务器到用来管理登录的系统级服务器在内的所有服务。基本上,一个「init system」的工作就是让所有面向用户(即非内核)的程序和服务运行起来。
(1)-(3) 中设计的特定命令和工具会因不同的「init system」而各有不同。Linux 系统历史上最通用的一个「init system」叫做「System V Init」,它是以极具影响力的 UNIX SYSTEM V 来命名的。在现在 Linux 系统中,同时被 CentOS、RedHad、Debian、Ubuntu 等等主流发行版本所采用的「init system」叫做「systemd init system」。
有两点需要铭记:
例如,Ubuntu 在
v15.04
中开始使用systemd
作为默认的「init system」。
很多时候,我们会想要终止那些占用了过多资源或者未响应的进程,两个常见的终止进程的命令是 kill
和 killall
。
kill
命令使用进程号 PID 来终止进程,我们可以通过 ps
命令来获取进程号。killall
命令通过给出进程名来终止进程,该命令会终止该进程名下的所有进程。
如果我们的 ps
命令有如下输出:
1 | $ ps |
现在有两个 bash
进程正在运行,一个的 PID 是 20735
,另一个的 PID 是 3086
。执行 kill 3086
会促使操作系统发送「graceful shutdown」信号给这个 bash
进程,但是如果执行 killall bash
命令,则会让操作系统终止所有 bash
进程。
默认情况下,kill
和 killall
命令会发送 TERM
信号给特定的进程。TERM
信号是一个「优雅」的终止信号,进程收到这个信号时会以合适的方式处理和结束进程。比如,被终止的进程可能想要在终止之前完成当前的任务、或者是清理可能会残留在系统中的临时文件等等。
如果一个进程有漏洞导致它已经不能响应 TERM
信号了,这种情况下我们就只能发送另一个比较激进的信号了,KILL
。有两种方法可以发送这个信号:
kill -KILL 3086
kill -9 3086
所有的信号都有一个数字编号,KILL
就是 9
。
kill -9
或者 killall -9
指令都是非常激进了,粗略地等同于直接拔掉计算机的电源。像这样来终止进程可能会留下一堆麻烦,只不过如果进程真的不响应了,也没啥别的办法。
所以,在使用 kill -9 PID
之前,一定要先尽量尝试使用 kill PID
才是。
ps
命令会给出一个当前运行进程的快照,而 top
命令则是给出一个持续更新、可排序的进程列表。top
命令常常被用来查看那个进程占用了最多的 CPU 或者内存。
下面是一些根据内存占用排序的 top
输出,用 ...
来做了部分省略:
1 | PID USER ... %CPU %MEM TIME+ COMMAND |
Linux 有这写通用的命令来操作 top
的输出结果:
P
(大写)可以按照 CPU 占用来排序M
(大写)可以按照内存占用来排序<
将排序列左移一栏>
将排序列右移一栏q
退出 top
你可以通过阅读 man top
来获取更多关于如何配置 top
的显示,也可以使用 htop
这个程序来实现更为强大的显示和功能效果。
比起使用 clone
方法,在 Java 中拷贝一个对象更加简单的办法是使用拷贝构造器。比方说,我们的 Person
类中有如下的构造函数:
1 | public Person(String name, int age) { |
那么就可以有这样的拷贝构造器:
1 | public Person(Person person) { |
该构造器可以使用和被拷贝对象同样的 name
和 age
属性,创建另一个 Person
对象。然而,必须要注意的是,拷贝不可变对象是完全没有必要的,所以我们只能用这种拷贝构造器来操作那些状态可变的对象。举例来说,只要 Person
类有这样的方法:
1 | public void setName(String name) { |
那么就大可使用拷贝构造器。
]]>更多资料,请参阅相关文档。
相较于手动地初始化具有初始元素的 set、list 和 map,Java 提供了另外一种更直接和简便的方法来快速完成:双花括号初始化。例如下方的代码:
1 | public Set<String> mySet = new HashSet<String>(); |
就可以利用双花括号初始化简化成这样:
1 | someFunction(new HashSet<String>() {{ |
]]>更多资料,请查看相关文档。
WeakHashMap
是一种特别的 Map
实现,它的所有键都存储在 WeakReference
中。相较于 HashMap
,WeakHashMap
与其功能基本完全一致,除了唯一一个显著的差别:如果 Java 的内存管理器不再有某个键对象的强引用,那么这个条目就会被从该 Map 中移除。
我们这样来创建一个 WeakHashMap
:
1 | HashMap map = new WeakHashMap(); |
我们可以通过引用某些对象的方式使用 WeakHashMap
来保存资源,但是同时允许这个资源在没有引用的时候被 Java 的垃圾回收器回收:
1 | System.gc(); |
所以大家普遍认为,可以通过 WeakHashMap
来解决缓存问题,因为当引用过期之后就会被丢弃。
这个类的另一种用法是创建 canonical map,你可以存储额外的属性在某个对象里面,因为当它们过期之后,WeakHashMap
的相应条目就会立马被丢弃。
]]>关于
WeakHashMap
的使用例子,请阅读参考资料。
工具类定义了一组通用的、功能复用的方法,它们不依赖于任何的对象,所以这些方法应该用 static
关键字声明成静态的。
1 | public class Utility { |
上面的例子中,multiply
方法就是静态的,所以我们不必生成任何 Utility
类的实例来调用该方法。
为了防止 Utility
类被调用于实例化,我们可以将构造函数用 private
关键字定义成私有的。
]]>更多关于静态方法的内容,请参阅相关文档。
使用 Linux 系统,不免会和用户和权限打交道,本文介绍了根权限和文件的权限属性等概念和应用。
在 Linux 中,su
命令和 sudo
命令有着十分巨大的区别:
su
命令会把你切换到根用户 root
sudo
会使用根权限来执行命令简单的说来,sudo
其实就是代表其他授权的用户来执行 root 命令的二进制 setuid。
我们可以通过修改(需要 root 权限)下列文件的中的用户列表,来决定哪些用户可以执行 sudo
命令:
1 | $ sudo /usr/sbin/visudo |
默认情况下,这个列表如下所示:
1 | #User privilege specification |
每一个 sudo
行的语法是:
1 | user machine=(effective_user) command |
通过上面的语法,我们可以授予某个用户 root 权限,其中每一个域代表:
user
是新的 sudo
用户的用户名machine
是 sudo
生效的主机名effective_user
代表被允许执行命令的有效用户command
代表这这个用户可以执行的一系列命令每一个文件和文件夹在被创建的时候都会被赋予一定的权限属性,这些值可以通过 umask
来指定。正如 umask
的名称所显示的那样,这个值本身其实就是一个可以禁用相应权限属性的掩码。
掩码表示一个有效的 4 位 8 进制数值。如果把少于 4 位的数值作为参数传入,高位会被用
0
补全。
默认情况下,文件夹在被创建的时候能获取的权限属性是 777
(rwxrwxrwx
),文件在被创建的时候能获取的权限属性是 666
(rw-rw-rw-
),二者的值都可以被被 umask
的掩码给减掉。
掩码过程相当于禁止掉相应的权限位,如果相应位上本身就不具备权限,那么掩码就不会起作用。比如说,如果使用 值为 111
的 umask
来创建一个文件,并不会影响文件的最终权限:
1 | rw-rw-rw- |
但是,如果 umask
的值是 333 的话,情况就不一样了,w
位和 x
位的权限都会被禁止掉:
1 | rw-rw-rw- |
我们可以这样来查看当前的 umask
值:
1 | $ umask |
如果我们要把当前会话中的 umask
设定为 077
的话,可以执行:
1 | $ umask 077 |
如果想要系统上的所有用户或者指定用户都使用设定的 umask
值的话,我们需要把相应的设定写入 /etc/profile
或者指定的 ~/.bashrc
文件中去。
字典是 Python 中非常常用的一种集合类型,今天我们来看一下关于字典的视图对象和映射类型。
Python 的字典提供以下三种方法来获取视图对象:
1 | dict.keys() |
视图对象将会动态地与字典的条目绑定,也就是说,当字典发生变化的时候,他的视图对象也会相应地发生变化。
我们可以通过 len(dictview)
方法来获取字典中条目的数量:
1 | 'one':1, 'two':2} a = { |
字典的 iter()
方法对字典的视图也行之有效,其会返回基于键、值或者键值对的迭代器:
1 | iter(keys) |
同样的,使用 in
关键词来判定集合的成员也可以同时用在字典或者字典的视图上:
1 | 'one' in keys |
更多关于字典的视图对象,请参阅官方文档。
字典(dict
)是 Python 的主要映射类型,它将可哈希化(hashable)的值映射为任意的对象。Python 中的字典和 Perl 语言、Ruby 语言中的哈希,C 语言中的哈希表是相似的。
我们可以使用 {key: value}
语法,dict
构造器或者会返回元组的 zip
方法来生成一个字典:
1 | d1 ={'first':1, 'second':2} |
在字典上获取和使用一个键的迭代器:
1 | it = iter(d1) |
用字典来更新另一个字典:
1 | "fruit": "apple", "car": "Ford"} prefs = { |
还可以用一个旧的字典(seq
)来构造一个新的字典,让新的字典和 seq
有相同的键:
1 | seq = ('one', 'two') |
]]>更多关于字典的标准映射类型,请参阅官方文档。
ipatable
是 Linux 内核自带的防火墙解决方案。它通过对经由网络的每一个包进行一系列的规则验证来决定该如何处理。
我们可以匹配协议类型、源地址和目的地址或者端口、接口以及它们和之前的包的关系等等。这些规则会被进一步的结构化成为规则链,网络包将会顺序地被规则链中的规则一一检查。它们可以被按需生成,但是有3种默认的规则:
INPUT
:处理流入服务器的流量。OUTPUT
:处理流出服务的流量。FORWARD
:处理流经服务器的流量而不停止它们。列出当前的规则:
1 | $ iptables -L -n |
列出当前的 NAT
规则:
1 | $ iptables -L -n -t nat |
阻断指定 IP 的流量:
1 | $ iptables -I INPUT -s 10.10.10.10 -j DROP |
允许指定 IP 的流量:
1 | $ iptables -I INPUT -s 10.10.10.10 -j ACCEPT |
允许指定端口的流量:
1 | $ iptables -I INPUT -p tcp -m tcp --dport 31415 -j ACCEPT |
-I
和 -A
参数的区别在于 -I
将会把指定的规则插入到规则链的最开始来抑制 -A
所增加的附带规则。
我们可以通过以下命令来检查当前路由表的防火墙状态:
1 | $ sudo iptables -L -n -v |
其中 -L
列出规则,-v
显示详细信息,我们通过 -n
标识禁止 DNS 方案来提高列出规则的速度。我们可以看到类似以下的输出:
1 | Chain INPUT (policy ACCEPT 0 packets, 0 bytes) |
其中有一条激活的 INPUT
规则,其阻止了来自 192.64.174.69 的所有流量。
]]>更多有关
ipatable
的使用,请参阅相关资料。
许多时候在 Java 中使用泛型是非常方便且必要的,但是我们不可能接受所有类型的参数来确保泛型的每一个功能都能得到维护。
为了解决这个问题,我们可以使用受限类型参数来限制泛型只能接受特定类型的实参。
1 | public <T extends Shape> |
上面这个方法是用来绘制一组形状(Shape
)的,如果我们使用不受限类型参数的泛型来实现这个方法的话,有可能导致的问题是其他类型可能并不能并不具备 draw()
方法。
通过指定 <T extends Shape>
我们可以确保只有 Shape
的子类可以被传递到这个方法中来。
]]>关于这一部分的更多内容,详见官方文档。
假设有下列接口:
1 | public interface Cooking { |
为了添加新的功能,直接向 Cooking
接口类中增加 microwave()
方法将会造成不少的麻烦。任何实现了 Cooking
接口的类现在都必须要同步更新实现这个方法,以确保整个类重新生效、正常工作。
为了避免这种情况,我们可以给 microwave()
方法一个默认 default
实现:
1 | public interface Cooking { |
因为 microwave()
方法已经在 Cooking
接口类中有了默认实现的定义,所有实现了该接口的类都不需要额外实现 microwave()
方法来确保其正常工作了。
这个方法在我们不破坏现有代码的情况下,想要增加一些新的功能时,十分的好用。
]]>Note:该方法需要 Java 8 以上的支持。详见官方文档。
GNU 文本程序实用技巧系列之——cat
。cat
这个命令是 UNIX 爱好者所热爱的,也是厌恶 UNIX 的人所憎恶的。
The
cat
utility reads files sequentially, writing them to the standard output.
有时候,我们常常需要将几个文件处理成一个文件,并将处理的结果保存到一个单独的输出文件中。cat
(「concatenate」的缩写)命令可以在其输入上接受一个或多个文件并将它们打印到一个单独的文件中。例如, cat chapter01 chapter02 chapter03 > book
将三个 chapterXX
文件保存在一个单独的 book
文件中。
输入文件按照它们在 cat
命令后的排列顺序被打印,因此,要调换输出文件中内容的顺序,就必须先调换输入文件的顺序。此外,当需要处理的文件数目过大而无法手工输入这些文件的名称时,可以使用通配符来匹配文件名,例如, cat chapter* > book
可以将当前目录下所有以 chapter
开头的文件全部合并输出到 book
文件中,记住,文件名将会按升序排列。这就意味着你会发现 chapter13
被发送到输出中时会在 chapter2
之前,chapter02
之后。有时候,这会引起一些很有意思的问题。
当 cat
的输出没有被重定向到一个文件或另一个命令的标准输入时,cat
表现出来的行为与多数命令行工具一样,即将其输出发送到控制台。 这意味着你可以使用 cat
来显示文件(也就是 cat
命令最常见的实用方法);例如,你可以使用 cat /etc/passwd
来显示系统密码文件的内容。为方便起见,你应该用 less
或者 more
来查看大文件,如 less /etc/passwd
。(你可以通过输入 man less
学习更多关于 less
的知识)。
尽管 cat
主要用于合并文件,我们还可以将它用于输入的简单自动处理。例如,你可以使用 一个单独的空白行来除去多行空白行(使用 -s
选项),这是一个在你将源代码公诸于世前进行代码整理工作的好办法。遗憾的是,cat
并没有用于一次清除所有空白行的选项。但这并不是什么大问题,因为你可以方便地使用 sed
命令将这些空白行除去:
1 | $ cat -s /etc/X11/XF86Config | sed '/^[[:space:]]*$/d' |
对于读取配置文件和 HTML 页面的源文件,特别是那些由脚本生成的插入了不必要新行的源文件,以及那些包含大型条件结构(其各个项之间已经用空行分开)的源文件来说,空白行紧缩是一个非常实用的技巧。
cat
的另外一个重要的功能是它可以对行进行编号。这种功能对于程序文档的编制以及法律和科学文档的编制很方便。打印在左边的行号使得参考文档的某一部分变得容易。这在编程、科学研究、业务报告或甚至是立法工作中都是非常重要的。 对行进行编号功能有两个选项: -b
选项(只能对非空白行进行编号)和 -n
选项(可以对所有行进行编号):
1 | $ cat -b /etc/X11/XF86Config |
cat
还可以在你查看包含如制表符这样的非打印字符的文件时起帮助作用。你可以用以下选项来显示制表符:
-T
将制表符显示为 ^I
-v
显示非打印字符,除了换行符和制表符,它们使用各自效果相当的「控制序列」。 例如,当你处理一个在 Windows 系统中生成的文件时,这个文件将使用 Control-M
( ^M
)来标记行的结束。对于代码大于 127 的字符,它们的前面将会被加上 M-
(表示「meta」),这与其它系统中在字符前面加上 Alt-
相当。-E
在每一行的结束处添加美元符( $
)。1 | $ cat -t /etc/X11/XF86Config |
Github 中有许多小技巧,今天给大家介绍两个常用的:如何在网页端新建文件夹和隐藏的快捷键操作。同时,介绍一款很实用的项目收藏查看软件给大家。
最近,常有朋友问我,如何在 Github 网页端里新建文件夹?确实,Github 网页端并没有明显的提示如何可以直接添加文件夹,只是有一个新建文件的按钮,但这并不代表这一操作没法在网页端完成,实际上你只需要在新建文件名时使用 /
来表示文件夹即可。
其实 Github 网页端提供了非常全面的快捷键操作,只不过提示也是隐藏得颇深。通过敲击 ?
键即可查看完整的快捷键列表。
其中最常用的像是 gc
快速回到 Code View,还有 t
打开文件列表(打开后继续键入字母可以模糊匹配文件名),以及 s
快速跳转到顶部的搜索框等等,都很实用。
最后给大家推荐一个 Mac 端的小软件——Star Order,它是一款支持 macOS/iOS 双平台的 Github Star 管理软件,面对日积月累的 Star 项目,你需要更灵活的标签管理方式或者更全面准确的排序检索,这款软件可以让你在面对众多 Star 仓库时,临危不乱,迅速找出目标项目,算是 Github 使用的必备伴侣。同类的另一个软件叫做 OhMyStar。
]]>其他别的什么小技巧,我想到了再补充吧。
当我们选择 AWS EC 作为服务器主机,而 AWS RDS 作为 MySQL 服务器时,如果通过 PHP 访问 MySQL 可能会出现 「Error establishing a database connection」错误,这是使用 WordPress 建站时常见的数据库连接错误。
一、确认自己的安全组权限
在 RDS 中需要为自己的数据库配置安全组权限,也即 3306
端口需要向 EC 主机开放:
其中,选择类型为 MYSQL/Aurora
,这样可以开启 3306
端口,把来源定义为我的 IP 以及 EC 主机所在安全组。(只需要键入主机名,AWS 可以自动适配)
二、关闭安全增强式 Linux(SELinux)
AWS EC 默认开启了 SELinux 是使得 PHP 服务器不能访问外部 MySQL 的元凶。使用 root
用户修改 EC 主机 /etc/selinux/config
文件中:
1 | SELinux = disabled |
重启 EC 主机,重新开启 httpd 服务即可。
]]>本文是项目 k-tmux 的说明文档,介绍了一套 tmux 的配置。本配置受到 @wlken 的启发。
ChangeLog: 2018-10-19 更新了弃用的配置命令,完善对鼠标的支持,修改了关闭窗口的键位绑定,安装并使用插件,增加对 prefix 状态和 buffer 复制状态的显示。
简单点说,tmux 是个终端复用器,允许你在一个终端中同时开启多个会话。
为什么要使用 tmux 呢?
通俗一点说,通常情况下,每次我们打开一个终端窗口的时候,其实我们是创建了一个和操作系统内核连接的会话。会话可以是本地的,也可以是通过 ssh 连接的。如果是使用 ssh 连接的,一旦连接中断了(网络问题、或者客户端不小心关掉了),那么整个会话也就断了,在会话中执行的命令和运行的程序都会中止。
使用 tmux 就不一样了。tmux 首先会创建一个 server 进程,你可以在 server 进程下创建会话(session),这里的会话有别于普通的会话,它是托管在 server 进程下的,只要 server 进程不被中止,session 不会因为意外中止(例如和 ssh 客户端断开连接)。任何时候你可以通过 attach
来接入这个会话。
下面我们看两个简单的场景:
你在公司/实验室开启了一个会话连接到本地或者 ssh 到某个服务器运行一个程序。程序持续运行着,还没有出结果,你得下班/放学回家了,放心的合上电脑走人即可。回到家,ssh 连接上服务器,attach
到之前的会话,你现在可以看结果了。
或者:
你连上某个服务器,打开 tmux,开启了一些需要后台长期执行的服务,然后关闭终端,走人。不用担心自己的服务进程因为关闭终端而中止。
那为什么说 tmux 是终端复用器?
我们来看看 tmux 的层次结构:
一个 tmux server 进程下可以托管多个会话(session),一个会话下面可以开启多个窗口(windows)——窗口就像正常终端中的 tab 标签页一样,一个窗口可以切割成多个窗格(pane)——其实窗格才是正常终端中的会话。
这样,我们就可以看出,tmux 在多个层级上做了复用:
下面看看 tmux 复用后的实际效果:
左下角显示了当前我所在的会话名称 Test
以及当前窗口和窗格编号 1-3
,下方中间部分显示了该会话下的窗口,当前激活的是窗口 [1:htop]
,右下角是系统时间。这是我自己配置的状态栏。
上方主体部分是当前窗口的窗格分割:
我在 1 中打开了 vim 编写文本,在 2 中使用 htop
查看系统进程,在 3 中准备执行某个命令。三个窗格互不干扰,平行工作,而且优雅整洁。
窗口 [2:~/blog]
中我还跑着我的博客服务器,和相关的配置等等,两边泾渭分明。
先通过查看 tmux 的版本号,自己是不是已经装了 tmux:
1 | tmux -V |
后续配置是针对 2.5
版本进行的,请确认自己的 tmux 的版本是 2.5+
。
建议使用 homebrew
来安装:
1 | brew install tmux |
1 | sudo apt-get install tmux |
如果 apt 源里面的 tmux 版本过于老旧,可以选择使用下面的办法从源码编译安装最新版本的 tmux。
这个要自己编译安装最新版本,我们先安装依赖:
1 | yum install gcc kernel-devel make ncurses-devel |
下载 libevent
并编译安装
1 | curl -OL https://github.com/libevent/libevent/releases/download/release-2.0.22-stable/libevent-2.0.22-stable.tar.gz |
下载 tmux v2.8 并编译安装
1 | curl -OL https://github.com/tmux/tmux/releases/download/2.8/tmux-2.8.tar.gz |
1 | 1. 如果需要的话,备份原有 tmux 配置 |
1 | git clone https://github.com/kchen0x/k-tmux.git |
若使用软链接的方式,不要删除 k-tmux 的真实目录。
k-tmux 的配置中使用了 TPM(Tmux Plugin Manager) 来管理插件,并且开启了其中的 prefix highlight 功能,可以指示当前的 prefix 状态和复制模式。如要启动需要先安装插件:
1 | git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm |
安装完成后进入 tmux,使用[prefix]加大写I
重载一次插件即可([prefix]为ctrl+a
)。
以下教程基于我的个人配置讲解,小部分特性和快捷键与官方默认有出入(不同的地方会做出说明),特此声明。另外,为了能够获得最佳体验,请使用 Solarized dark 配色,详情请见 「八卦阴阳鱼,谈谈 Solarized 配色」。
操作前缀
[PREFIX-]
:tmux 中所有的命令都需要先按下操作前缀ctrl+a
。(官方默认为ctrl+b
,已更改,主要是为了和 screen 保持一致,同时也更方便按)
下面有
$
命令行提示符的是在原生终端中输入的直接作用于 tmux server 的命令。此外都在 tmux 的会话中键入。注意区分大小写。
1 | # 创建, tmux new -s <name-of-my-session> 创建一个新的会话 |
1 | # 创建一个新的窗口 |
1 | # 垂直/水平分割窗口(原先未修改键位的分割方式是[PREFIX-%]和[PREFIX-"]) |
1 | # 进入复制模式 |
1 | # 获得快捷键列表 |
tmux 最大的优点是全键盘操作,使得很多操作变得快捷又优雅。但是缺点也是显而易见的,就是有些时候不大方便:
PREFIX-[
进入复制模式,然后通过 VIM 风格进行翻页。(jk和 ctrl-u
/ctrl-d
)所以为了照顾鼠标用户,我在配置中默认开启了鼠标模式(mouse reporting)。
在鼠标模式下,你可以:
q
键退出复制模式。建议大家还是多使用快捷键完成操作,增加工作效率。
想要关闭关闭鼠标模式,请进入命令模式然后:
1 | # 进入命令模式 |
当然也可以直接去配置文件里修改相关的配置。想要修改的配置立马生效,可以使用:
1 | # 重载 tmux 配置 |
最后再提醒一次大家,善用 [PREFIX-?]
快捷键帮助,再配合 /
查找命令,使用起来便可如鱼得水。祝大家使用愉快!
iTerm2 最新的特性已经集成了 tmux,这意味着什么?
通常情况下,当你使用 tmux 的时候,会在一个「物理」窗口(Window)中创建多个虚拟的窗口。你可以通过在 tmux 中使用各种命令来操作它的环境,但这样也会随之带来一些问题:
control + b
,这和 emacs 中的左移光标是冲突的,而且这也会让与 shell 的交互变得更加困难)。对于大多数的用户而言,在终端中使用复用器(Multiplexer)是十分好用的工作方式,但是他们并不想接受以上的种种缺陷。
iTerm2 与 tmux 的集成(iTerm2’s tmux integration)就解决了这些痛点。
当你执行 tmux -CC
命令时一个新的 tmux 会话就会被创建,一个看上去和普通 iTerm2 窗口没有差别的窗口将会被打开。唯一不同的地方就是,当 iTerms2 退出或者是 ssh 会话丢失时,tmux 会保持运行。你可以重新连接上刚刚 ssh 连接的远程主机,然后执行 tmux -CC attach
命令,iTerm2 窗口会重新打开并恢复到断开时相同的状态。那么,一些应用场景就不难想象了:
对于那些常常使用 ssh 的小伙伴来说,你可以:
而对于所有小伙伴而言,你可以:
你可以一如往常那般使用 tmux,只需要在末尾加上 -CC
参数就可以了,实际上,也就是执行以下任意一个命令:
1 | tmux -CC |
当你执行 tmux -CC
命令的时候,你将会在终端中看到如下的菜单:
1 | ** tmux mode started ** |
esc
键,tmux 窗口会关闭,tmux 客户端也会终止。esc
键但是任何事情都没有发生,这说明 tmux 的客户端可能崩溃了或者是除了别的状况。这时按下 X
键来强制 iTerm2 退出 tmux 模式。如果真是的 tmux 客户端崩溃的话,你也许会需要执行 stty sane
命令来恢复你的终端状态。L
键来重现问题,tmux 协议命令会被打印到屏幕上。C
键来进入 tmux 命令模式,一个可以输入命令的对话框将会弹出,你可以键入类似 new-window
这样的命令。通常情况下, 大多数的动作都不需要通过键入命令来实现,以下的一些 iTerm2 的动作就可以直接作用于 tmux:
split-window
分割 tmux 窗口。resize-pane
命令调整 tmux 窗格大小。tmux -CC attach
命令重新与之连上。大多数的限制都将会在接下来的版本中得到解决和改进:
.tmuxrc
文件未经测试,可能运转不正常。你需要使用1.8或更高版本的 tmux,在 Mac 上安装 tmux 最简便的方法是使用 homebrew
:
1 | brew install tmux |
]]>