mac terminal的一些困惑

记录一些困扰很久的问题

what’s shell

先上百科解释,简而言之shell(壳)是相对kernel(内核)而言的,对于操作系统来说,shell暴露了一个接口给用户,用户可以通过这个接口调用操作系统的指令。shell的主要主要工作就是解释用户输入的命令或者执行用户按照shell语法写的文件。这样就诞生出来了好多shell程序,比如 bash/sh/ksh/csh(*nix)或者windows上的cmd.

Unix 系统上诞生了两个主要的shell血统 Bourne shell (包括 sh,ksh,and bash) 和 C shell (包括 csh and tcsh)

GNU 计划是很有意思的,是“GNU’s Not Unix”的递归缩写,因为当时Unix是一款商业的操作系统,然后就有人要造反做自由软件,他的倡导人是RichardStallman,最后最大的产出是Linux系统。

在mac系统上执行 ntop$ ls /bin/*sh 会看到mac已经自带了大部分的shell程序

/bin/bash	/bin/ksh	/bin/tcsh
/bin/csh	/bin/sh		/bin/zsh

shell/console/terminal

刚刚分清了各种*sh,那shell/console/terminal又是什么东西呢,好像我们在平时使用的时候认为他们同一个东西,搜索之后发现了这里

在过去terminal和console指硬件设备,现在的系统中他们都是一个软件。

那为什么经常又看到iterm/iterm2/oh-my-zsh/等等呢,他们又是什么怎么回事呢?

iterm2 是 iterm 的升级版本,它和mac自带的terminal.app一样也是terminal(终端模拟器),但是它比自带的terminal多了很多功能,交互做的更好。oh-my-zsh 不是shell也不是terminal/console 它是一个zsh配置管理的框架(这要归功于zsh配置的灵活性,导致很多人为他写了很多个性化的配置,并形成了一个社区)。所以要想把自己的zsh搞得花花绿绿,可以直接配置一个oh-my-zsh主题就行了。

如何配置一个好用的shell ?

现在看来zsh在各方面已经完全超越其他的各种shell(但是在mac或者大部分系统上默认并不是zsh,abcdf…zsh 意指shell的尽头)。终端模拟器方面iterm2最好用了,但是本人不太喜欢它的图标。oh-my-zsh 是必须要有的因为我希望有高亮显示各种花花绿绿的关键词。

所以最后选择的方案是:zsh + oh-my-zsh

安装oh-my-zsh只需要一条命令,在官网上可以找到这条命令:curl -L https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh sh

直接执行,然后重启终端 ———— 已经变彩色了!如果默认shell不是zsh在安装的过程中会提示把默认的shell设置成zsh。

环境变量

其实本文最开始想写的就是环境变量的配置问题,因为不经常使用mac的缘故每次配置的时候都要在网搜索一番,然后看到有的要修改 ‘/etc/profile’ 有的要修改 ‘~/.profile’ 有的要修改 ‘~/.bashrc’。并且由于OS X系统版本的变迁和shell程序不同还会出现好多配置失效的情况,大部分情况下mac上的环境变量配置只能用一坨屎来形容。

如果打开了一个终端,最简单的方式配置环境变量是这样做,在中终端执行(以 Android adb 命令示例)

ntop$export PATH=$PATH:/Users/ntop/Library/Android/sdk/platform-tools
ntop$adb version
    Android Debug Bridge version 1.0.32

但是这样做只能保持这次的环境变量配置只能维持在当前进程里面,如果关闭程序或者新开一个终端,这个设置就会失效(这显然不是我们想要的)。

在Windows上只要在高级设置里面配置环境变量就可以了,简单明了,但是在mac上官方是没有答案的,于是好多程序员开始研究了各种配置方式,从权限角度可以分全局配置(System-Wide)和用户配置(User-Wide)。全局配置的结果是每个用户都能共享配置,用户配置只能给当前配置了的用户使用。

全局配置

修改‘/etc/profile’文件

这个文件可以配置好多东西,环境变量只是其中一项。

一般这个文件的配置如下

#Set file creation mask
unmask 022
#Tell me when new mail arrives
MAIL=/usr/mail/$LOGNAME
#Add my /bin directory to the shell search sequence
PATH=/usr/bin:/usr/sbin:/etc::
#Set terminal type
TERM=lft
#Make some environment variables global
export MAIL PATH TERM

在mac上打开这个文件可能内容和上面并不一样,不过没有关系,在文件最后加上一句 export PATH=$PATH:/Users/ntop/Library/Android/sdk/platform-tools 在我的系统上大概是这样的

➜  ~  cat /etc/profile 
# System-wide .profile for sh(1)

if [ -x /usr/libexec/path_helper ]; then
	eval `/usr/libexec/path_helper -s`
fi

if [ "${BASH-no}" != "no" ]; then
	[ -r /etc/bashrc ] && . /etc/bashrc
fi

export PATH=$PATH:/Users/ntop/Library/Android/sdk/platform-tools

新开一个终端,执行 adb shell 会打印 zsh: command not found: adb, 恩,我们遇到了第一个坑,‘/etc/profile’ 只对bash有效对 zsh 是无效的(我在前面已经把默认的shell设置成了zsh)。可以通过 chsh -s /bin/bash 命令把终端的默认shell修改回bash,这时候再执行

ntop$ adb version
Android Debug Bridge version 1.0.32

It works!!!

修改‘/etc/paths’或‘/etc/paths.d/’

详细的解释见这里 大概意思就是如果你的’/etc/profile’文件中默认是这样写的

# System-wide .profile for sh(1)

if [ -x /usr/libexec/path_helper ]; then
	eval `/usr/libexec/path_helper -s`
fi

if [ "${BASH-no}" != "no" ]; then
	[ -r /etc/bashrc ] && . /etc/bashrc
fi

那么 eval `/usr/libexec/path_helper -s`这句话的意思是调用path_helper程序来设置环境变量,这个程序呢会寻找两个地方

  1. ‘/etc/paths’ 这个文件大概这样
     /usr/local/bin
     /usr/bin
     /bin
     /usr/sbin
     /sbin
    

    直接把自己的环境变量路径加进去就行了。

  2. ‘/etc/paths.d/’ 这是一个文件夹,系统会读取这个文件夹里面所有的文件中得环境变量配置,我的系统中只有一个go语言的环境变量配置,大概如下
     ntop$ ls /etc/paths.d
     go
     ntop$ cat /etc/paths.d/go
     /usr/local/go/bin
    

相对于修改 ‘/etc/paths’ 在 ‘/etc/paths.d/’ 下面添加一个文件来解决问题感觉更好一些,所以我做了如下配置

ntop$ ls /etc/paths.d
android	go
ntop$ cat /etc/paths.d/android
/Users/ntop/Library/Android/sdk/platform-tools

但是无论是修改’/etc/paths’ 还是 ‘/etc/paths.d’ 都是只有在使用bash的时候才有生效,对于zsh来说都是无效的(呵呵)。

用户配置

用户级别的配置大部分都是在修改 ~ 目录下的配置文件,网上随便一搜,又是一大堆的配置文件,这些配置文件有的再 ~ 目录下可以找到有的是找不到的,而且他们的配置针对的shell也不一样,下面逐一说明。

首先要看一下你用的是什么shell,执行 echo $SHELL 会打印当前的shell类型,如果是bash可以编辑下面三个文件,这三个文件也有坑,注意。

  1. ’~/.profile’ 相当于 ‘/etc/profile’ 作用域在当前用户,会覆盖 ‘/etc/profile’
  2. ’~/.bash_profile’ runs only with login shells i.e when you first log in into system.
  3. ’~/.bashrc’ runs every time you open a new non-login bash shell such as xterm / aterm

如果是csh配置 ‘~/.cshrc’ 如果是zsh配置’~/.zshrc’ (终于到了我自用的shell了)

这些文件在~目录下未必会有,如果没有的话,需要自己创建,配置的语法都是一样的,关键是要看自己使用的shell是哪一种类型。

export PATH=$PATH:/Users/ntop/Library/Android/sdk/platform-tools

对于bash而言如果仅仅做一些简单的环境变量配置,去理解 ‘~/.profile’,’~/.bash_profile’ 和 ‘~/.bashrc’ 的不同,未免太过复杂,简而言之,可以这样配置。

  1. bash 配置 ‘~/.bashrc’
  2. csh 配置 ‘~/.cshrc’
  3. zsh 配置 ‘~/.zshrc’

对于前面描述的全局配置而言,只能作用于bash ,对于csh和zsh的全局配置目前还没有调研清楚,以后明白了再补充。

听了同事的建议,可以在 ‘.zshrc’ 文件中 source 一下 bash 的相关配置,比如:source ~/.bashrc

最后我使用的zsh配置是这样的

➜  ~  cat .zshrc
....

# User configuration

export PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"

# Android
export PATH=$PATH:/Users/ntop/Library/Android/sdk/platform-tools

# export MANPATH="/usr/local/man:$MANPATH"

source $ZSH/oh-my-zsh.sh
....
nTop 06 June 2015
blog comments powered by Disqus