Linux学习札记(三):shell的使用和系统管理命令

本篇主要归纳总结Shell脚本的编写和系统管理部分的知识点。

shell scripts

根据提示输入

1
read -p "first number: " firstnu

数值计算

1
2
3
value1=12
value2=24
value3=$(($value1*value2))

文件目录的查看、判断操作

test 后加“!”为取反操作即值为“true”时返回“false”

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
test -e /dmtsai && echo "exist" || echo "Not exist" #查看是否存在
test -f file1 #判断是否为文件
test -d dir1 #判断是否为目录
test -z string #判断字符串是否为空
```
## 使用"[]"进行判断
```bash
#判断name是否为“jim”,每个空格不能少
[ "$name" = "jim" ]
#根据输入‘y’或‘n’进行后继操作,忽略大小写
read -p "Please input (Y/N): " yn
[ "$yn" == "Y" -o "$yn" == "y" ] && echo "OK, continue" && exit 0
[ "$yn" == "N" -o "$yn" == "n" ] && echo "Oh, interrupt!" && exit 0
```
## 判断可执行文件后的参数
```bash
if [ "$1" == "hello" ]; then
echo "Hello, how are you ?"
elif [ "$1" == "" ]; then
echo "You MUST input parameters, ex> $0 someword"
else
echo "The only parameter is 'hello'"
fi

计算退伍日期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 1. 告知使用者这支程序的用途,并且告知应该如何输入日期格式?
echo "这是用来计算退伍日期的 :"
read -p "请输入日期(YYYYMMDD ex>20050401): " date1
# 2. 测试一下,这个输入的内容是否正确?利用正规表示法啰~
date_d=`echo $date1 |grep '[0-9]\{8\}'`
if [ "$date_d" == "" ]; then
echo "You input the wrong format of date...."
exit 1
fi
# 3. 开始计算日期. declare -i 声明一个变量为数字类型
declare -i date_dem=`date --date="$date2" +%s`
declare -i date_now=`date +%s`
declare -i date_total_s=$(($date_dem-$date_now))
declare -i date_d=$(($date_total_s/60/60/24))
if [ "$date_total_s" -lt "0" ]; then
echo "You had been demobilization before: " $((-1*$date_d)) " ago"
else
declare -i date_h=$(($(($date_total_s-$date_d*60*60*24))/60/60))
echo "You will be demobilized after $date_d days and $date_h hours."
fi

case语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
case $1 in
"one")
echo "Your choice is ONE"
;;
"two")
echo "Your choice is TWO"
;;
"three")
echo "Your choice is THREE"
;;
*)
echo "Usage {one|two|three}"
;;
esac

函数

函数声明要放在程序前面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function printit(){
echo -n "Your choice is "
}
echo "This program will print your selection !"
case $1 in
"one")
printit; echo $1 | tr 'a-z' 'A-Z'
;;
"two")
printit; echo $1 | tr 'a-z' 'A-Z'
;;
"three")
printit; echo $1 | tr 'a-z' 'A-Z'
;;
*)
echo "Usage {one|two|three}"
;;
esac

循环

while语句

1
2
3
4
while [ "$yn" != "yes" ] && [ "$yn" != "YES" ]
do
read -p "Please input yes/YES to stop this program: " yn
done

util语句

1
2
3
4
until [ "$yn" == "yes" ] || [ "$yn" == "YES" ]
do
read -p "Please input yes/YES to stop this program: " yn
done

for语句

1
2
3
4
for animal in dog cat elephant
do
echo "There are ""$animal""s.... "
done

计算1+…+100的和

while语句

1
2
3
4
5
6
7
8
s=0
i=0
while [ "$i" != "100" ]
do
i=$(($i+1))
s=$(($s+$i))
done
echo "The result of '1+2+3+...+100' is ==> $s"

for语句

1
2
3
4
5
6
s=0
for (( i=1; i<=100; i=i+1 ))
do
s=$(($s+$i))
done
echo "The result of '1+2+3+...+100' is ==> $s"

判断文件或目录是否存在

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash
if [ ! -e test ]; then
touch test
echo "Just make a file test"
exit 1
elif [ -e test ] && [ -f test ]; then
rm test
mkdir test
echo "remove file ==> test"
echo "and make directory test"
exit 1
elif [ -e test ] && [ -d test ]; then
rm -rf test
echo "remove directory ==> test"
exit 1
else
echo "Does here have anything?"
fi

取出第一列内容,输入每一行及行号

1
2
3
4
5
6
7
#!/bin/bash
accounts=`cat /etc/passwd | cut -d':' -f1`
for account in $accounts
do
declare -i i=$i+1
echo "The $i account is \"$account\" "
done

debug

1
2
3
4
5
6
7
[hui@linux ~]$ sh -x sh15.sh #加-x,代码在执行前显示出来
+ PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/home/vbird/bin
+ export PATH
+ for animal in dog cat elephant
+ echo 'There are dogs.... '
There are dogs....
...

系统管理

切换身份

  • su 直接切换成root
  • su - 切换root后,相关设置也发生变化

查看最近登录

  • lastlog 读取 /var/log/lastlog 文件,显示登录信息

多用户通信

  • talk
  • write user #使用命令后,可发送文字内容
  • mesg n 禁止其它用户使用write命令发信息时打断自己,使用mesg y重新启动
  • wall “words” 与其它所有的用户通信,如果没有使用mesg n关掉服务,则收到
1
2
3
4
5
6
7
8
[vbird@linux ~]$ mail dmtsai -s "nice to meet you" admin@linux.net
Hello, D.M. Tsai
Nice to meet you in the network.
You are so nice. byebye!
. #这里很重要喔,结束时,最后一行输入小数点 . 即可!
Cc: #这里是所谓的『副本』,不需要寄给其它人,所以直接 [Enter]
[vbird@linux ~]$ mail dmtsai -s "nice to meet you" < filename #使用数据流
  • mail 可用来查看邮件

df命令,用于显示磁盘分区上的可使用的磁盘空间。

  • -h,选项以KB以上的单位来显示,可读性高
  • -a ,查看全部文件系统

at命令

在指定时间执行一次命令。可在/etc/at.deny里面设置无法使用此命令的账户。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#再过五分钟后,将 /root/.bashrc 寄给 dmtsai 这个使用者
[hui@linux ~]$ at now + 5 minutes
at> /bin/mail dmtsai -s "testing at job" < /root/.bashrc
at> <EOT> <==这里输入 #[ctrl] + d 就会出现 <EOF> ,代表结束!
#在 2005/09/15 23:00 关机
[hui@linux ~]$ at 23:00 2005-09-15
at> /bin/sync
at> /bin/sync
at> /sbin/shutdown -h now
at> <EOT>
[hui@linux ~]$ atq #查询当前有多少个工作安排
[hui@linux ~]$ atrm 10 #将第2个移除

crontab命令

用以循环执行任务crontab 是读到内存当中的,所以在你修改完/etc/crontab 之后,可能并不会马上执行, 这个时候请重新启动
crond,输入/etc/init.d/crond restart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#用账户每天12:00发邮件给自己,前五个数字依次为分钟、时、日、月、周
[hui@linux ~]$ crontab -e
0 12 * * * mail hui -s "at 12:00" < /home/dmtsai/.bashrc
#每五分钟需要执行 /home/dmtsai/test.sh
[hui@linux ~]$ crontab -e
*/5 * * * * /home/dmtsai/test.sh #最好使用绝对路径
#每个星期五下午 4:30 告诉你朋友星期六的约会不要忘记
[hui@linux ~]$ crontab -e
30 16 * * 5 mail friend@his.server.name < /home/dmtsai/friend.txt
[hui@linux ~]$ crontab -l #查询所有crontab任务
[hui@linux ~]$ crontab -r #删除所有crontab任务,删除某个必需使用crontab -e

命令后加“&”使程序在后台运行

  1. jobs命令,查看后台任务
  • -l :除了列出 job number 之外,同时列出 PID;
  • -r :仅列出正在背景 run 的任务;
  • -s :仅列出正在背景当中暂停 (stop) 的任务。
1
2
[hui@linux ~]# fg <==预设取出标记为 + 的任务
[hui@linux ~]# fg %n <==取出指定任务到前台,n job号!

kill和killall,杀死进程

1
2
3
4
5
6
7
8
9
10
11
hui@linux ~]$ kill -l #列出所有的signal,比如SIGKILL(-9)
#杀死某个后台任务
#-1是重启该进程,-9是强制停止任务,-15是用正常方式停止(默认),生成的临时文件会自动删除
hui@linux ~]$ jobs
[1] Stopped vim jv.*
[2] Stopped vim data1
hui@linux ~]$ kill -9 %1
#强制终止所有以 httpd 启动的进程,-I忽略大小写
[root@linux ~]# killall -9 httpd

ps,查看运行的进程

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
#将此次登录的PID与相关信息显示出来
#F flag,4代表使用者为super user;S 进程状态,含义见下条命令STAT;PID;C CPU百分比;PRI 优先级,越小越容易被执行;NI nice;
#ADDR kernel function,如果是running用“-”表示;SZ 占用内存;WCHAN 程序是否运行,“-”表示正在运行;
#TTY 登录使用的tty;TIME 使用掉的CPU时间;CMD 下达的指令
hui@hui-virtual-machine:~/test$ ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1000 16508 16497 0 80 0 - 6156 wait pts/3 00:00:00 bash
...
#显示出正在内存中运行的进程
#VSZ 使用掉的虚拟内存;RSS 占用的固定内存;STAT R 运行中或可运行,S 睡眠,T 正在侦测或停止,
#Z zombie僵尸进程,已经停止,但其父进程无法终止
hui@hui-virtual-machine:~/test$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.2 182488 4476 ? Ss 8月20 0:09 /sbin/init splash
root 2 0.0 0.0 0 0 ? S 8月20 0:00 [kthreadd]
#以第一条命令的形式列出所有运行中的进程
hui@hui-virtual-machine:~/test$ ps -al
#以进程树的形式显示
hui@hui-virtual-machine:~/test$ ps -axjf
#找出与 cron 与 syslog 这两个服务有关的 PID 号码
hui@hui-virtual-machine:~/test$ ps aux|egrep '(cron|syslog)'
syslog 824 0.0 0.1 255896 2800 ? Ssl 8月20 0:02 /usr/sbin/rsyslogd -n
root 831 0.0 0.1 30612 2364 ? Ss 8月20 0:00 /usr/sbin/cron -f
hui 1769 0.0 0.3 435756 7832 ? Sl 8月20 0:14 /usr/bin/pulseaudio --start --log-target=syslog

top命令,查看系统运行情况

top交互按键

  • h:显示帮助画面,给出一些简短的命令总结说明;
  • k:终止一个进程;
  • i:忽略闲置和僵死进程,这是一个开关式命令;
  • q:退出程序;
  • r:重新安排一个进程的优先级别;
  • S:切换到累计模式;
  • s:改变两次刷新之间的延迟时间(单位为s),如果有小数,就换算成ms。输入0值则系统将不断刷新,默认值是5s;
  • f或者F:从当前显示中添加或者删除项目;
  • o或者O:改变显示项目的顺序;
  • l:切换显示平均负载和启动时间信息;
  • m:切换显示内存信息;
  • t:切换显示进程和CPU状态信息;
  • c:切换显示命令名称和完整命令行;
  • M:根据驻留内存大小进行排序;
  • P:根据CPU使用百分比大小进行排序;
  • T:根据时间/累计时间进行排序;
  • w:将当前设置写入~/.toprc文件中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#每两秒更新一次top,观察整体信息
hui@hui-virtual-machine:~/test$ top -d 2
top - 21:14:34 up 2 days, 11:02, 2 users, load average: 0.00, 0.01, 0.05
Tasks: 265 total, 1 running, 263 sleeping, 0 stopped, 1 zombie
%Cpu(s): 2.0 us, 1.0 sy, 0.0 ni, 97.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 2032280 total, 1798160 used, 234120 free, 109944 buffers
KiB Swap: 2094076 total, 188336 used, 1905740 free. 349904 cached Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
16497 hui 20 0 635352 40012 25708 S 3.0 2.0 2:08.62 gnome-terminal-
...
#将 top 的信息进行 2 次,然后将结果输出到 /tmp/top.txt
[hui@linux ~]$ top -b -n 2 > /tmp/top.txt
#查看某一PID的进程
[hui@linux ~]$ top -d 2 -p10604

pstree命令以树状图的方式展现进程之间的派生关系

1
2
3
4
#以进程树形式查看进程的相关性
hui@hui-virtual-machine:~/test$ pstree -A
#同时显示PID和users
hui@hui-virtual-machine:~/test$ pstree -Aup

free命令可以显示当前系统未使用的和已使用的内存数目,还可以显示被内核使用的内存缓冲区。

free [-b|-k|-m|-g] [-t]

参数:

-b :直接输入 free 时,显示的单位是 Kbytes,可以使用 b(bytes), m(Mbytes),k(Kbytes), 及 g(Gbytes) 来显示单位

-t :在输出的最终结果,显示物理内存与 swap 的总量。

uptime,查看已开机时间

nice和renice,调整程序优先级

PRI(new) = PRI(old) + nice

1
2
[hui@linux ~]$ nice [-n] command #n值在-20~19之间
[hui@linux ~]$ renice 10 18852 #将 18852 那个 PID 修改 nice 为 10

fuser,查看正在使用某文件或目录的进程

1
2
3
4
5
6
7
8
9
[hui@linux ~]$ fuser /var/
[hui@linux~]$ fuser -ki /var/spool/postfix/public/qmgr #找出使用该目录的进程并杀死其PID
```
## **pidof**命令,查看相关程序的PID
```bash
#init 以及 syslogd 这两个程序的 PID
[hui@linux ~]$ pidof init syslogd

自定义启动开机程序

把需要开机的命令,写进/etc/rc.local文件里即可。