终端的概念

我们在使用 Linux 时,并不是直接与系统打交道,而是通过一个叫做 Shell 的中间程序来完成的,在图形界面下为了实现让我们在一个窗口中完成用户输入和显示输出,Linux 系统还提供了一个叫做终端模拟器的程序(Terminal)。常见的终端模拟器: gnome-terminal,Konsole,xterm,rxvt,kvt,nxterm 和 eterm 。

Shell

Shell 是指“提供给使用者使用界面”的软件(命令解析器),类似于 DOS 下的 command(命令行)和后来的 cmd.exe

普通意义上的 Shell 就是可以接受用户输入命令的程序。它之所以被称作 Shell 是因为它隐藏了操作系统底层的细节。同样的 UNIX/Linux 下的图形用户界面 GNOME 和 KDE,有时也被叫做“虚拟 shell”或“图形 shell”。

UNIX/Linux 操作系统下的 Shell 既是用户交互的界面,也是控制系统的脚本语言。当然这一点也有别于 Windows 下的命令行,虽然该命令行也提供了很简单的控制语句。在 Windows 操作系统下,有些用户从来都不会直接使用 Shell,然而在 UNIX 系列操作系统下,Shell 仍然是控制系统启动、X11 启动和很多其它实用工具的脚本解释程序。

在 UNIX/Linux 中比较流行的常见的 Shell 有 bash、zsh、ksh、csh 等等,Ubuntu 终端默认使用的是 bash,默认的桌面环境是 GNOME 或者 Unity(基于 GNOME)。

什么是oh my zsh?

Oh My Zsh 是一款社区驱动的命令行工具。它基于 zsh 命令行,提供了主题配置,插件机制,已经内置的便捷操作。给我们一种全新的方式使用命令行。支持语法高亮,代码补全等。

zsh-2

什么是zsh?

zsh是一个Linux下强大的shell, 大多数Linux产品安装以及默认使用bash shell, 但这丝毫不影响极客们对zsh的热衷, 几乎每一款Linux产品都包含有zsh,通常可以用apt-get、urpmi或yum等包管理器进行安装。

zsh是bash的增强版,其实zsh和bash是两个不同的概念,zsh更加强大。通常zsh配置起来非常麻烦,且相当的复杂,所以oh-my-zsh是为了简化zsh的配置而开发的,因此oh-my-zsh算是zsh的配置。

安装

本文使用的是Ubuntu(20.04.1)系统进行安装演示。

安装之前需要安装Git:sudo apt install git -y

查看系统当前使用shell

echo $SHELL

chensir@ubantu:~$ echo $SHELL
/bin/bash

查看系统自带哪些shell

cat /etc/shells

chensir@ubantu:~$ cat /etc/shells
# /etc/shells: valid login shells
/bin/sh
/bin/bash
/usr/bin/bash
/bin/rbash
/usr/bin/rbash
/bin/dash
/usr/bin/dash

安装zsh

sudo apt install zsh -y

安装之后 使用 cat /etc/shells 查看系统的shell有 /usr/bin/zsh说明安装成功。

chensir@ubantu:~$ cat /etc/shells
# /etc/shells: valid login shells
/bin/sh
/bin/bash
/usr/bin/bash
/bin/rbash
/usr/bin/rbash
/bin/dash
/usr/bin/dash
/bin/zsh
/usr/bin/zsh

设置zsh为默认shell

chsh -s /bin/zsh

然后重启:sudo reboot

安装oh my zsh(推荐方法3)

方法1

sh -c "$(curl -fsSL https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"

如果提示 zsh: command not found: curl,则需要安装curl,执行 sudo apt install curl -y,安装成功后再执行方法1。

安装完成curl再执行方法1还会出现错误提示 curl: (35) OpenSSL SSL_connect: 连接被对方重设 in connection to raw.github.com:443

则尝试方法2或方法3,方法3成功的几率高一些。

方法2

sh -c "$(wget https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)"

如果执行方法2提示 无法建立 SSL 连接。 则直接使用方法3。

方法1和方法2是官网给出的两种安装方法,但由于github的服务器大多数都在国外连接难免会出现问题,可以通过科学上网的方式来解决。但科学上网不是本章重点所以不做过多描述哈。

方法3

安装时可能由于网络原因会导致连接超时等问题,解决办法是在本地新建一个install.sh的脚本:vi install.sh 添加内容如👇:

#!/bin/sh
#
# This script should be run via curl:
# sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
# or via wget:
# sh -c "$(wget -qO- https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
# or via fetch:
# sh -c "$(fetch -o - https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
#
# As an alternative, you can first download the install script and run it afterwards:
# wget https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh
# sh install.sh
#
# You can tweak the install behavior by setting variables when running the script. For
# example, to change the path to the Oh My Zsh repository:
# ZSH=~/.zsh sh install.sh
#
# Respects the following environment variables:
# ZSH - path to the Oh My Zsh repository folder (default: $HOME/.oh-my-zsh)
# REPO - name of the GitHub repo to install from (default: ohmyzsh/ohmyzsh)
# REMOTE - full remote URL of the git repo to install (default: GitHub via HTTPS)
# BRANCH - branch to check out immediately after install (default: master)
#
# Other options:
# CHSH - 'no' means the installer will not change the default shell (default: yes)
# RUNZSH - 'no' means the installer will not run zsh after the install (default: yes)
# KEEP_ZSHRC - 'yes' means the installer will not replace an existing .zshrc (default: no)
#
# You can also pass some arguments to the install script to set some these options:
# --skip-chsh: has the same behavior as setting CHSH to 'no'
# --unattended: sets both CHSH and RUNZSH to 'no'
# --keep-zshrc: sets KEEP_ZSHRC to 'yes'
# For example:
# sh install.sh --unattended
# or:
# sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
#
set -e

# Track if $ZSH was provided
custom_zsh=${ZSH:+yes}

# Default settings
ZSH=${ZSH:-~/.oh-my-zsh}
REPO=${REPO:-ohmyzsh/ohmyzsh}
REMOTE=${REMOTE:-https://github.com/${REPO}.git}
BRANCH=${BRANCH:-master}

# Other options
CHSH=${CHSH:-yes}
RUNZSH=${RUNZSH:-yes}
KEEP_ZSHRC=${KEEP_ZSHRC:-no}


command_exists() {
command -v "$@" >/dev/null 2>&1
}

fmt_error() {
printf '%sError: %s%s\n' "$BOLD$RED" "$*" "$RESET" >&2
}

fmt_underline() {
printf '\033[4m%s\033[24m\n' "$*"
}

fmt_code() {
# shellcheck disable=SC2016 # backtic in single-quote
printf '`\033[38;5;247m%s%s`\n' "$*" "$RESET"
}

setup_color() {
# Only use colors if connected to a terminal
if [ -t 1 ]; then
RED=$(printf '\033[31m')
GREEN=$(printf '\033[32m')
YELLOW=$(printf '\033[33m')
BLUE=$(printf '\033[34m')
BOLD=$(printf '\033[1m')
RESET=$(printf '\033[m')
else
RED=""
GREEN=""
YELLOW=""
BLUE=""
BOLD=""
RESET=""
fi
}

setup_ohmyzsh() {
# Prevent the cloned repository from having insecure permissions. Failing to do
# so causes compinit() calls to fail with "command not found: compdef" errors
# for users with insecure umasks (e.g., "002", allowing group writability). Note
# that this will be ignored under Cygwin by default, as Windows ACLs take
# precedence over umasks except for filesystems mounted with option "noacl".
umask g-w,o-w

echo "${BLUE}Cloning Oh My Zsh...${RESET}"

command_exists git || {
fmt_error "git is not installed"
exit 1
}

ostype=$(uname)
if [ -z "${ostype%CYGWIN*}" ] && git --version | grep -q msysgit; then
fmt_error "Windows/MSYS Git is not supported on Cygwin"
fmt_error "Make sure the Cygwin git package is installed and is first on the \$PATH"
exit 1
fi

git clone -c core.eol=lf -c core.autocrlf=false \
-c fsck.zeroPaddedFilemode=ignore \
-c fetch.fsck.zeroPaddedFilemode=ignore \
-c receive.fsck.zeroPaddedFilemode=ignore \
--depth=1 --branch "$BRANCH" "$REMOTE" "$ZSH" || {
fmt_error "git clone of oh-my-zsh repo failed"
exit 1
}

echo
}

setup_zshrc() {
# Keep most recent old .zshrc at .zshrc.pre-oh-my-zsh, and older ones
# with datestamp of installation that moved them aside, so we never actually
# destroy a user's original zshrc
echo "${BLUE}Looking for an existing zsh config...${RESET}"

# Must use this exact name so uninstall.sh can find it
OLD_ZSHRC=~/.zshrc.pre-oh-my-zsh
if [ -f ~/.zshrc ] || [ -h ~/.zshrc ]; then
# Skip this if the user doesn't want to replace an existing .zshrc
if [ "$KEEP_ZSHRC" = yes ]; then
echo "${YELLOW}Found ~/.zshrc.${RESET} ${GREEN}Keeping...${RESET}"
return
fi
if [ -e "$OLD_ZSHRC" ]; then
OLD_OLD_ZSHRC="${OLD_ZSHRC}-$(date +%Y-%m-%d_%H-%M-%S)"
if [ -e "$OLD_OLD_ZSHRC" ]; then
fmt_error "$OLD_OLD_ZSHRC exists. Can't back up ${OLD_ZSHRC}"
fmt_error "re-run the installer again in a couple of seconds"
exit 1
fi
mv "$OLD_ZSHRC" "${OLD_OLD_ZSHRC}"

echo "${YELLOW}Found old ~/.zshrc.pre-oh-my-zsh." \
"${GREEN}Backing up to ${OLD_OLD_ZSHRC}${RESET}"
fi
echo "${YELLOW}Found ~/.zshrc.${RESET} ${GREEN}Backing up to ${OLD_ZSHRC}${RESET}"
mv ~/.zshrc "$OLD_ZSHRC"
fi

echo "${GREEN}Using the Oh My Zsh template file and adding it to ~/.zshrc.${RESET}"

sed "/^export ZSH=/ c\\
export ZSH=\"$ZSH\"
" "$ZSH/templates/zshrc.zsh-template" > ~/.zshrc-omztemp
mv -f ~/.zshrc-omztemp ~/.zshrc

echo
}

setup_shell() {
# Skip setup if the user wants or stdin is closed (not running interactively).
if [ "$CHSH" = no ]; then
return
fi

# If this user's login shell is already "zsh", do not attempt to switch.
if [ "$(basename -- "$SHELL")" = "zsh" ]; then
return
fi

# If this platform doesn't provide a "chsh" command, bail out.
if ! command_exists chsh; then
cat <<EOF
I can't change your shell automatically because this system does not have chsh.
${BLUE}Please manually change your default shell to zsh${RESET}
EOF
return
fi

echo "${BLUE}Time to change your default shell to zsh:${RESET}"

# Prompt for user choice on changing the default login shell
printf '%sDo you want to change your default shell to zsh? [Y/n]%s ' \
"$YELLOW" "$RESET"
read -r opt
case $opt in
y*|Y*|"") echo "Changing the shell..." ;;
n*|N*) echo "Shell change skipped."; return ;;
*) echo "Invalid choice. Shell change skipped."; return ;;
esac

# Check if we're running on Termux
case "$PREFIX" in
*com.termux*) termux=true; zsh=zsh ;;
*) termux=false ;;
esac

if [ "$termux" != true ]; then
# Test for the right location of the "shells" file
if [ -f /etc/shells ]; then
shells_file=/etc/shells
elif [ -f /usr/share/defaults/etc/shells ]; then # Solus OS
shells_file=/usr/share/defaults/etc/shells
else
fmt_error "could not find /etc/shells file. Change your default shell manually."
return
fi

# Get the path to the right zsh binary
# 1. Use the most preceding one based on $PATH, then check that it's in the shells file
# 2. If that fails, get a zsh path from the shells file, then check it actually exists
if ! zsh=$(command -v zsh) || ! grep -qx "$zsh" "$shells_file"; then
if ! zsh=$(grep '^/.*/zsh$' "$shells_file" | tail -1) || [ ! -f "$zsh" ]; then
fmt_error "no zsh binary found or not present in '$shells_file'"
fmt_error "change your default shell manually."
return
fi
fi
fi

# We're going to change the default shell, so back up the current one
if [ -n "$SHELL" ]; then
echo "$SHELL" > ~/.shell.pre-oh-my-zsh
else
grep "^$USERNAME:" /etc/passwd | awk -F: '{print $7}' > ~/.shell.pre-oh-my-zsh
fi

# Actually change the default shell to zsh
if ! chsh -s "$zsh"; then
fmt_error "chsh command unsuccessful. Change your default shell manually."
else
export SHELL="$zsh"
echo "${GREEN}Shell successfully changed to '$zsh'.${RESET}"
fi

echo
}

main() {
# Run as unattended if stdin is not a tty
if [ ! -t 0 ]; then
RUNZSH=no
CHSH=no
fi

# Parse arguments
while [ $# -gt 0 ]; do
case $1 in
--unattended) RUNZSH=no; CHSH=no ;;
--skip-chsh) CHSH=no ;;
--keep-zshrc) KEEP_ZSHRC=yes ;;
esac
shift
done

setup_color

if ! command_exists zsh; then
echo "${YELLOW}Zsh is not installed.${RESET} Please install zsh first."
exit 1
fi

if [ -d "$ZSH" ]; then
echo "${YELLOW}The \$ZSH folder already exists ($ZSH).${RESET}"
if [ "$custom_zsh" = yes ]; then
cat <<EOF

You ran the installer with the \$ZSH setting or the \$ZSH variable is
exported. You have 3 options:

1. Unset the ZSH variable when calling the installer:
$(fmt_code "ZSH= sh install.sh")
2. Install Oh My Zsh to a directory that doesn't exist yet:
$(fmt_code "ZSH=path/to/new/ohmyzsh/folder sh install.sh")
3. (Caution) If the folder doesn't contain important information,
you can just remove it with $(fmt_code "rm -r $ZSH")

EOF
else
echo "You'll need to remove it if you want to reinstall."
fi
exit 1
fi

setup_ohmyzsh
setup_zshrc
setup_shell

printf %s "$GREEN"
cat <<'EOF'
__ __
____ / /_ ____ ___ __ __ ____ _____/ /_
/ __ \/ __ \ / __ `__ \/ / / / /_ / / ___/ __ \
/ /_/ / / / / / / / / / / /_/ / / /_(__ ) / / /
\____/_/ /_/ /_/ /_/ /_/\__, / /___/____/_/ /_/
/____/ ....is now installed!


EOF
cat <<EOF
Before you scream Oh My Zsh! please look over the ~/.zshrc file to select plugins, themes, and options.

• Follow us on Twitter: $(fmt_underline https://twitter.com/ohmyzsh)
• Join our Discord server: $(fmt_underline https://discord.gg/ohmyzsh)
• Get stickers, shirts, coffee mugs and other swag: $(fmt_underline https://shop.planetargon.com/collections/oh-my-zsh)

EOF
printf %s "$RESET"

if [ $RUNZSH = no ]; then
echo "${YELLOW}Run zsh to try it out.${RESET}"
exit
fi

exec zsh -l
}

main "$@"

保存之后执行 授权可执行权限 chmod +x install.sh

开始执行脚本 ./install.sh

如果出现👇的错误:

正克隆到 '/home/chensir/.oh-my-zsh'...
fatal: 无法访问 'https://github.com/ohmyzsh/ohmyzsh.git/':gnutls_handshake() failed: Error in the pull function.
Error: git clone of oh-my-zsh repo failed

错误原因:由系统的 git 默认使用的 libcurl4-gnutls-dev 造成

解决方法=>执行:apt-get -y install build-essential nghttp2 libnghttp2-dev libssl-dev

然后再次执行安装脚本 ./install.sh

安装成功的画面

zsh-3

个性化设置及安装插件

配置主题

编辑隐藏文件 .zshrc vi ~/.zshrc

ZSH_THEME="robbyrussell" 修改为 ZSH_THEME="ys" ,ys这个主题比较简约,不会喜欢的小伙伴可以自行更换为其它主题,zsh主题列表 ,修改之后重新加载配置文件 source ~/.zshrc

自动提示

  • 下载插件:克隆仓库到本地
git clone git://github.com/zsh-users/zsh-autosuggestions $ZSH_CUSTOM/plugins/zsh-autosuggestions
  • 修改 .zshrc 文件,找到插件设置命令,默认是 plugins(git),把它修改为 plugins=(git zsh-autosuggestions)
  • 重启终端(新开一个终端即可)

PS:如果重新打开终端看不到自动提示,可能是终端的字体颜色太淡了,可以通过👇配置把字体改亮一些:

进入到相关目录:

cd ~/.oh-my-zsh/custom/plugins/zsh-autosuggestions

修改自动提示相关的配置文件:ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=10'

vi zsh-autosuggestions.zsh

# 将 ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=8' 修改为 ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=10'

语法高亮

安装插件

sudo apt install zsh-syntax-highlighting

修改配置文件

echo "source /usr/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh" >> ~/.zshrc

重新加载

source ~/.zshrc

重新打开终端窗口可以看到效果。