More Related Content
Similar to 1, shell intro
Similar to 1, shell intro (20)
1, shell intro
- 3. 介绍
• shell中文翻译是”壳”, 事实上shell的确可以被
理解为环绕在linux核心之外的一层壳, 用户
通过shell与系统核心进行交互;
• 从系统的层面来看, shell实际上是操作系统
的一个进程, 该进程会接收用户的输入并执
行相应的命令. System Call
用户输入 Shell Process Kernel
- 4. Shell的历史
• shell是与unix/linux系统紧密联系在一起的, 并
伴随着后者不断地发展, 历史上Unix shell有以
下里程碑事件:
1, 1977年Bourne Shell发布, 并推动了Unix Shell
的标准化;
2, 70年代末, 基于BSD系统的C shell发布;
3, 80年代中期基于Bourne Shell的Korn Shell被发
布;
4, Bash Shell(Bourne Again Shell)成为linux系统
的默认shell, 同时很多Unix上的shell被移植过来.
- 5. Shell的种类
• shell主要有以下几种类型:
Bash: bourne again shell
C Shell: 脚本风格类似于c语言的shell版本
Bourne Shell: 最早版本的shell
Korn Shell: 可以被理解为Bourne Shell的
增强版本
• 使用以下命令查看系统shell系统
1, 查看系统安装的shell
cat /etc/shells
2, 当前使用的shell
echo $SHELL
- 6. 用户登录shell
• 用户在登录系统时会启动对应的shell, 该shell在
用户被创建时指定或者取默认值
(/etc/default/useradd); 对于前者可以查看
/etc/passwd文件, 示例:
demo:x:500:500:demo user:/home/demo:/bin/bash
这里demo用户登录时会执行/bin/bash, bash就
是该用户的登录shell.
• 如果不希望某个用户登录系统, 可以指定
/sbin/nologin为登录shell, 通常这些用户只用于
运行某些后台进程, 比如daemon用户.
- 7. 命令行的解析
• shell工作的第一步是对用户输入的命令进行解析执行,
该过程分为以下几步:
1, 将命令行分解为token(词), 词使用空格或者制表符分隔;
2, 根据分解后的第一个token来判断是否为内置命令或
磁盘上的可执行程序, 对于前者则在当前的shell进程中
执行, 比如cd/echo/exit等; 对于磁盘命令则fork一个子进程
执行,比如ls/grep/awk等, 当子进程在执行时当前shell进入休
眠状态, 子进程执行结束时再唤醒当前shell;
具体命令的执行过程又大体可以分为以下几步:
1, 设置重定向, 后台进程和管道;
2, 执行变量替换比如$name, $user等;
3, 执行命令替换如`date`;
4, 执行称为globbing的文件名替换;
5, 执行命令.
- 8. 命令类型
- 内置命令
• bash有如下常用的内置命令
. 执行脚本文件, 同source;
alias 查看或者创建别名;
unalias 删除某个别名
echo 打印字符串
eval 执行动态命令, 比如: eval “ls -l”
exec 运行命令, 替换当前shell
help 查看内置命令的信息, 比如: help exec
history 查看历史命令
let 算数运算
kill 向进程发送信号, kill -l查看信号列表
fg 将后台作业调到前台
bg 将作业设置为后台作业
jobs 显示所有后台作业
- 9. 命令类型
- 内置命令 & 可执行程序
cd 切换目录
pwd 显示当前目录
pushd 向目录堆栈中增加项
popd 从目录堆栈中删除项
umask 查看或设置文件掩码
type 查看命令类型, 比如: type pwd显示内置命令
• 可执行程序
可执行程序指的已经编译可用于执行的二进制程序,
bash在当前的PATH环境变量中查找这些程序, 使用
echo $PATH查看有哪些路径, 这些路径使用:分开. 示
例: ls -l
bash将ls当成是可执行命令, 在PATH中查看, 最终将
会找到/bin/ls可执行程序
- 10. 命令类型
- 别名 & 函数 & 优先级
• 别名通常是指用alias命令定义的程序缩写, 比
如: alias ll=“ls -l”, 在执行ll命令时, 实际上执行
的ls -l命令;
• 函数是与其它编程语言类型是一个程序代码块,
用于实现特定的功能. 示例:
function hell {echo hello}
输入hello即可以调用该函数.
• shell判断命令类型的优先级:
1), 别名 2), 函数
3), 内置命令 4), 可执行程序
- 11. 命令
- 退出状态
• shell在某个二进制程序或者内置命令执行完
毕时, 会设置一个退出状态码, 0表示执行成
功, 非0表示执行失败. 该状态码可以通过$?
进行查看, 示例:
• 程序退出状态在shell编程中会经常被使用到,
因为很多shell脚本都需要根据命令的执行情
况来决定下一步的动作.
- 12. 进程与系统调用
• 进程是正在运行的程序, 由PID唯一标识并由内
存控制和管理. 进程由可执行程序, 进程数据和
堆栈, 程序指针和堆栈指针, 寄存器以及程序运
行时所需要的所有信息组成. 使用ps/pstree命
令查看当前的进程;
• 系统调用是进程与内核之间的桥梁, 通过系统
调用可以使进程从用户态陷入到内核态, 从而
访问内核提供的各种服务, 下面是系统调用的
一分完整列表:
http://www.ibm.com/developerworks/cn/linux/k
ernel/syscall/part1/appendix.html
- 13. 系统调用
- fork/wait/exec/exit
• 与shell执行相关的系统调用:
fork 如果用户输入被解析为可执行程序或者脚本, 那么
shell会使 用fork系统调用派生一个子进程执行该程
序;使用pstree -pa $$命令进行测试.
wait 当fork的子进程处理重定向, 管道和后台处理时, 系
统调用wait使父进程进入休眠状态直至子进程终止;
exec 子shell在执行可执行程序时, 会调用exec系统调用加
载该程序, 比如输入ls -l那么子shell会执行exec ls -l命
令; 程序被加载之后子shell进程被新的进程取代, 新
的进程在完成之后通过系统调用exit推出并唤醒父
shell;
exit 进程通过exit系统调用退出;
• 以ls命令进行说明
键入ls命令之后, shell派生一个子进程(fork), 开始休眠
(wait). 子进程通过exec调用ls程序, ls进程代替子shell. ls
完成之后通过exit退出, 并唤醒父进程.
- 14. 环境变量
• 环境变量就是在当前shell中可以访问到的变量, 通常环
境变量全部使用大写; 用户在登录过程中默认会设置一
些环境变量, 比如:HOME/LOGNAME/PATH/SHELL;
• 相关命令
export
可以使用shell内置命令export定义新的环境变量, 比如:
export VAR1=“VAR1”;
env
env命令查看当前的环境变量
• 环境变量通常会被应用程序使用到, 比如oracle数据库
SID环境变量ORACLE_SID, JAVA环境变量JAVA_HOME等; 经
常需要设置的一个环境变量是PATH, 用于查找可执行程
序, 在用户HOME目录的.bash_profile文件中设置, 比如:
export PATH=/path/to:$PATH
这里添加了一个新的路径到已有的变量中.
- 15. shell环境
• shell在启动时需要对工作环境进行相应的初始化工作, 其中主要
包括环境变量的定义, shell环境包括以下方面:
1, 所有权
所有权的设置决定了用户进程读写文件的权限; 所有权设置会设
置如下环境变量: UID(真实用户ID), GID(真实组ID), EUID(有效用
户ID), EGID(有效组ID); EUID/EGID实际决定了用户操作文件的权
限;
2, 掩码(umask)
用户在创建文件时, 该文件具有默认的权限; 这些权限是由当前
的掩码决定的, 具体参考:《 4, Files & Folders》
3, 用户信息
shell初始化时, 需要设置一些当前的用户信息, 包括: 当前工作目
录(PWD), 用户名(USER), 主目录(HOME), 登录名(LOGNAME), 邮件
路径(MAIL)等;
4, 其他
可以使用env命令查看其他的环境变量信息.
- 16. shell环境的继承
• shell在启动子shell执行程序的时候, 子shell会继
承父shell的环境信息, 这些信息除了上一页讲
到的之外还包括父shell的文件描述符信息:
文件描述符(file descriptor)是一个比较小的无
符号整数, 用于标识打开的文件, 管道和套接字;
头三个文件描述符0/1/2分别表示标准输入
(stdin), 标准输出(stdout)和标准错误(stderr); 当
用户打开一个文件时, 一个新的文件描述符会
被分配, 如果文件描述符被使用完, 则无法打开
文件.
- 17. 管道
• 管道(pipe),用来将一条命令的输出传递给另一
条命令作为输入. 示例:
其中”|”被称为管道描述符.
• 管道是通过打开与关闭文件描述符来实现的,
此时的文件描述符被称为管道文件描述符; 上
述示例中, 首先打开了管道文件描述符, 然后派
生子进程who和wc; who进程往管道中写数据,
wc进程从中读取数据. 使用如下命令可以观察
到这种行为:
- 18. 信号
• 可以通过shell发送信号给某个指定的进程,
该进程在接收到信号之后在采用相应的动
作. shell提供了内置命令kill给进程发送信号,
如该名称所示信号通常用于终止某个进程.
示例:
# 给2425号进程发送SIGKILL信号导致该进程终止
kill -9 2425
• 标准信号列表可参考: TODO
- 19. 脚本文件
• 除了通过交互式的命令与shell进行交互之外还可以通过脚本文
件(script file)的方式进行, 通常脚本文件用于执行较为复杂的一
些动作; shell脚本文件通常以.sh作为后缀名, 通过chmod命令将
脚本文件设置为可执行.
• 脚本文件(以demo.sh为例)通常使用以下两种方式执行:
1, ./demo.sh
首先会派生一个子进程, 并在该子进程中执行脚本;
2, source demo.sh
使用此方式执行不要求用户对脚本文件有可执行权限, 另外脚本
会在当前shell中执行, 相当于将文件中的脚本拷贝出来在当前
shell中交互式执行. 使用如下脚本进行验证:
#!/bin/bash
echo $$
ps -ef | grep $$
3, 使用bash命令
bash demo.sh, 与1类似
Editor's Notes
- 系统调用 与 库函数:c语言的库函数基本上都会调用相关的系统调用,比如fread会调用read系统调用;库函数与系统调用的区别在于, 库函数是可移植的, 而系统调用通常依赖于平台.
- Note: 与环境变量不同的是, 子shell不会继承父shell的局部变量.