Shell

  1. Shell Script
  2. 查看默认的shell
  3. Shebang
  4. Profile File
    1. System Profile File
    2. User Profile
  5. 类型 Type
    1. 交互式 Shell 与 非交互式 Shell
    2. 登录式的Shell 与 非登陆式的Shell
  6. 网络
    1. netstat
  7. Cheat Sheet
    1. PROMPT_COMMAND
    2. alias
    3. 数组 array
    4. 字符串
    5. 变量

shell 是访问操作系统的服务的一个用户接口user interface。而使用该接口的方式有两种:命令行接口command-line interface (cli) 、图形化用户接口 graphical user interface (GUI)[wiki]

Shell Script

shBourne shell/bin/sh 。sh是一个标准,并不是具体应用。因为sh不是具体应用,所以调用/bin/sh将会连接到具体应用。[stackoverflow]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# centos 7
$ ls -tlr /bin/sh
lrwxrwxrwx. 1 root root 4 May  1 07:05 /bin/sh -> bash
# 查看版本
$ sudo yum install -y redhat-lsb-core 
$ lsb_release -a
LSB Version:    :core-4.1-amd64:core-4.1-noarch
Distributor ID: CentOS
Description:    CentOS Linux release 7.8.2003 (Core)
Release:        7.8.2003
Codename:       Core


# ubuntu 18
$ ls -tlr /bin/sh
lrwxrwxrwx 1 root root 4 Sep  8  2019 /bin/sh -> dash
# 查看版本
$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 18.04.4 LTS
Release:	18.04
Codename:	bionic
  • bashBourne Again shell :是兼容sh的具体应用。
  • cshC shell
  • kshKorn shell
  • tcshTC shell</sup>
  • zshZ shell

查看默认的shell

查看Default Login Shell:[stackoverflow]

1
2
3
4
5
6
7
8
9
$ echo $SHELL
/bin/bash
$ $SHELL --version
GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

使用 ps $$ 可查看Current Shell,[stackoverflow] 下面是通过shebang去设置Current Shell进行的对照实验Control Experiment

1
2
3
4
5
6
7
8
# shebang为空时,将执行/bin/bash
$ cat << EOF > test00.sh
> ps \$\$
> EOF
$ chmod +x test00.sh
$ ./test00.sh
   PID TTY      STAT   TIME COMMAND
 52859 pts/8    S+     0:00 /bin/bash --rcfile /home/xiaojie/.local/share/JetBrains/Toolbox/apps/PyCharm-P/ch-0/202.63
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# shebang为/bin/sh时,将执行/bin/sh
$ cat << EOF > test01.sh
> #!/bin/sh
> ps \$\$
> EOF
$ chmod +x test01.sh
$ ./test01.sh
   PID TTY      STAT   TIME COMMAND
 52863 pts/8    S+     0:00 /bin/sh ./test01.sh

# shebang为/bin/bash时,将执行/bin/bash
$ cat << EOF > test02.sh
> #!/bin/bash
> ps \$\$
> EOF
$ chmod +x test02.sh
$ sh test02.sh
   PID TTY      STAT   TIME COMMAND
 52867 pts/8    S+     0:00 sh test02.sh
$ ./test02.sh
   PID TTY      STAT   TIME COMMAND
 52869 pts/8    S+     0:00 /bin/bash ./test02.sh
1
2
3
4
# 命令行状态下,将执行/bin/bash
$ ps $$
   PID TTY      STAT   TIME COMMAND
 52210 pts/8    Ss     0:00 /bin/bash --rcfile /home/xiaojie/.local/share/JetBrains/Toolbox/apps/PyCharm-P/ch-0/202.63

Shebang

shebang有若干种:

1
2
3
#!/usr/bin/env bash
#!/bin/bash
#!/bin/sh

其中为了兼容不同系统,推荐使用:

1
#!/usr/bin/env bash

该语句env bash可以理解成,查找PATH路径中的bash程序并运行,通过我们会将/bin等路径放到PATH中。[stackoverflow][GNU]

Profile File

A profile file is a start-up file of an UNIX user.[来源] profile file这里可以译成描述文件

System Profile File

无论使用什么Shell,在登录系统时都会执行 /etc/profileSystem Profile File[oracle]

User Profile

在这之后,将执行User Profile。当用户启动新的terminal时,将执行该文件。根据设置的默认Shell,将会执行相应的Profile File。 [oracle]

Shell Profile File
Ksh、sh ~/.profile
Bash ~/.bash_profile
Csh ~/.login

类型 Type

交互式 Shell 与 非交互式 Shell

Interactive Shell 通常会将信息读写到用户的terminal。[gnu]

通过以下"$-" 可以判断shell是否为Interactive 。[gnu]

1
2
3
4
5
6
7
8
9
10
# interactive
$ echo "$-" 
himBH 

# non-interactive
$ cat <<  EOF > test.sh
> echo "\$-" 
> EOF
$ sh test.sh
hB

himBH通过man手册可查到以下信息:

  • h: Remember the location of commands as they are looked up for execution. This is enabled by default.
  • i: interactive
  • m: Monitor mode. Job control is enabled
  • B: The shell performs brace expansion (see Brace Expansion above). This is on by default
  • H: Enable ! style history substitution. This option is on by default when the shell is interactive.

i意味着Interactive Shell。由示例可知,Non-Interactive Shell 通常是通过代码执行命令,而Interactive Shell则通常是通过命令行窗口执行。

登录式的Shell 与 非登陆式的Shell

通过以下实验,我们可以对 Login Shell 有一个大致的印象:

1
2
3
4
5
6
$ vagrant ssh
$ shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'
Login shell
$ exit
$ shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'
Not login shell

通过Shopt命令,我们可以了解到shell的所有行为选项。[GNU]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
$ shopt 
autocd          off
cdable_vars     off
cdspell         off
checkhash       off
checkjobs       off
checkwinsize    on
cmdhist         on
compat31        off
compat32        off
compat40        off
compat41        off
direxpand       off
dirspell        off
dotglob         off
execfail        off
expand_aliases  on
extdebug        off
extglob         on
extquote        on
failglob        off
force_fignore   on
globstar        off
gnu_errfmt      off
histappend      on
histreedit      off
histverify      off
hostcomplete    off
huponexit       off
interactive_comments    on
lastpipe        off
lithist         off
login_shell     on
mailwarn        off
no_empty_cmd_completion off
nocaseglob      off
nocasematch     off
nullglob        off
progcomp        on
promptvars      on
restricted_shell        off
shift_verbose   off
sourcepath      on
syslog_history  off
xpg_echo        off
$ shopt | grep login_shell
login_shell     on

Login Shell vs Not Login Shell

通过执行bash man命令,我们可以了解到Login Shell

When bash is invoked as an interactive login shell, or as a non-interactive shell with the –login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. The –noprofile option may be used when the shell is started to inhibit this behavior.

When a login shell exits, bash reads and executes commands from the files ~/.bash_logout and /etc/bash.bash_logout, if the files exists.

Login Shell登录后,依次执行:

  1. /etc/profile
  2. ~/.bash_profile
  3. ~/.profile

退出后:

  1. ~/.bash_logout/etc/bash.bash_logout

Not Login Shell时的行为则是:

When an interactive shell that is not a login shell is started, bash reads and executes commands from ~/.bashrc, if that file exists. This may be inhibited by using the –norc option. The –rcfile file option will force bash to read and execute commands from file instead of ~/.bashrc.

执行文件:

  1. ~/.bashrc

网络

netstat

1
2
3
4
5
6
7
8
9
10
11
# 所有
netstat -a

# 进程
# -p, --programs           display PID/Program name for sockets
# -l, --listening          display listening server sockets
sudo netstat -lp
# -n, --numeric            don't resolve names  不解析,比如:localhost将会以127.0.0.形式显示
# -t|--tcp   只看TCP
sudo netstat -lpn
sudo netstat -lpnt

更多查看:https://linux.cn/article-2434-1.html

Cheat Sheet

PROMPT_COMMAND

修改命令行样式:

1
2
3
# 命令行展示时间
$ export PROMPT_COMMAND="echo -n \[\$(date +%H:%M:%S)\]\ "
[02:21:13] $ 

alias

~/.bashrc~/.bash_aliases 中添加 alias 所定义的字符串,它将会成为一个可执行命令

1
2
3
# 定义
# ~/.bashrc
$ alias cd_home='cd ~/; echo hello;'
1
2
3
4
# 执行
~/.aws$ cd_home
hello
~$ 

数组 array

打印数组

1
echo "my array is:" "${arr[@]}"

循环(with index)

1
2
3
4
for ((i = 0; i < ${#array[@]}; ++i)); do
    position=$(( $i + 1 ))
    echo "$position,${array[$i]}"
done

循环

1
2
3
4
# 循环 optional parameters
for op in "$@"; do
	echo $op
done

字符串

切割

1
2
3
# 切成两半 split into two parts
str="key=value"
IFS="=" read -r str1 str2 <<<"$str"

变量

默认值

1
FOO="${变量名:-默认值}"