Linux SHELL 스 크 립 트 프로 그래 밍 상세 설명

Linux SHELL 스 크 립 트 프로 그래 밍
  • 스 크 립 트 프로 그래 밍 상세 설명
  • 명사 해석
  • 셸 스 크 립 트
  • 스 크 립 트 의 조건 테스트
  • bash 테스트 분류
  • 스 크 립 트 의 상태 반환 값
  • 스 크 립 트 문법 검 측 과 디 버 깅 실행
  • 프로 그래 밍 스 크 립 트 의 사용자 상호작용
  • 스 크 립 트 실행 방식
  • 1. 선택 집행
  • if 문장
  • case 문장
  • 2. 순환 집행
  • 2.1 for 순환
  • LIST 목록 의 생 성 방식
  • for 순환 예시
  • for 순환 의 특수 용법
  • 2.2 while 순환
  • 2.3 순환 까지
  • 스 크 립 트 예제
  • 1. vim 은 네 개의 문 자 를 자동 으로 들 여 쓰 는 방법 을 설정 합 니 다.
  • 2. 세 사용 자 를 자동 으로 추가 하고 이 세 사용자 의 uid 의 합 을 계산 합 니 다.
  • 3. 명령 을 통 해 두 텍스트 파일 경 로 를 스 크 립 트 에 전달 하고 빈 줄 의 합 을 계산 합 니 다.
  • 4. 매개 변 수 를 통 해 사용자 이름 을 스 크 립 트 에 전달 하고 이 사용자 가 저장 하지 않 을 때 추가 합 니 다.
  • 5. 명령 행 매개 변 수 를 통 해 두 개의 숫자 를 정 하고 그 중에서 비교적 큰 수 치 를 출력 합 니 다.
  • 6. 스 크 립 트 매개 변 수 는 스 크 립 트 에 파일 경 로 를 전달 하여 이 파일 의 유형 을 판단 합 니 다.
  • 7. 스 크 립 트 에 매개 변 수 를 전달 합 니 다. 이 매개 변 수 는 사용자 이름 입 니 다.ID 번호 에 따라 사용자 유형 을 판단 합 니 다.
  • 8. 스 크 립 트 를 작성 할 때 다음 과 같이 요구 합 니 다.
  • 9. 각각 100 이내 의 모든 짝수 의 합 과 모든 홀수 의 합 을 구한다.
  • 10. 현재 시스템 의 모든 id 의 합 을 계산 합 니 다.
  • 11. 스 크 립 트 매개 변 수 를 통 해 스 크 립 트 에 디 렉 터 리 를 전달 한 다음 에 이 디 렉 터 리 에 있 는 모든 텍스트 파일 의 줄 수 를 계산 합 니 다.이 파일 의 총 수 를 설명 합 니 다.
  • 12. 계산/etc/passwd 파일 의 10 번 째 사용자 와 20 번 째 사용자 의 id 번호 의 합.
  • 13./etc/rc. d/init. d/functions 와/etc/inittab 파일 의 공백 줄 수 를 계산 합 니 다.
  • 14. 스 크 립 트 를 작성 하여 172.16.141. X 네트워크 에서 어떤 호스트 주소 가 사용 되 고 사용 되 지 않 았 는 지 찾 아 결 과 를 해당 파일 에 저장 합 니 다.
  • 15. 스 크 립 트 를 작성 하여 C 류, B 류 또는 A 류 네트워크 의 모든 호스트 가 온라인 인지 확인 할 수 있 습 니 다.
  • 16. 스 크 립 트 를 작성 하고 명령 행 매개 변 수 를 통 해 사용자 이름 을 입력 하여 ID 가 짝수 인지 홀수 인지 판단 합 니 다.
  • 17. while, for 순환 으로 10.0.0.1/24 네트워크 에 생존 하 는 IP 주소
  • 를 각각 검사 합 니 다.
    스 크 립 트 프로 그래 밍 상세 설명
    编程语言的分类:根据运行方式
    	1、编译运行:源代码 --> 编译器 (编译)--> 程序文件
    	2、解释运行:源代码 --> 运行时启动解释器,由解释器边解释边运行
    
    根据其编程过程中功能的实现是调用库还是调用外部的程序文件:
    	1、shell脚本编程:利用系统上的命令及编程组件进行编程
    	2、完整编程:利用库或编程组件进行编程
    
    编程模型:过程式编程语言,面向对象的编程语言
    程序=指令+数据
    	1、过程式:以指令为中心来组织代码,数据是服务于代码;
    		顺序执行
    		选择执行
    		循环执行
    		代表:C,bash
    	2、对象式:以数据为中心来组织代码,围绕数据来组织指令;
    		类(class):实例化对象,method;
    		代表:Java, C++, Python
    

    해석
    变量:
    	1、局部变量
    	2、本地变量
    	3、环境变量
    	4、位置参数变量
    	5、特殊变量
    
    具体参考:
    https://blog.csdn.net/weixin_44983653/article/details/95232625
    
  • 위치 매개 변수 변수
  • 位置参数变量 :主要是向脚本传递参数。
    
    # myscript.sh  argu1 argu2
    
    引用方式:
    	argu1 argu2
          $1,   $2, ..., ${10},  ${11}, ...
    				
    轮替:
    	shift  [n]:位置参数轮替
    
    示例:
    root@LeeMumu:~# cat echo.sh           # 通过此脚本,了解位置参数变量
    #!/bin/bash
    
    echo $1
    echo $2
    
    root@LeeMumu:~# ./echo.sh "The line 1." "The line 2."
    The line 1.
    The line 2.
    
  • 특수 변수
  • $0:脚本文件路径本身
    $#:脚本参数的个数
    $*:所有参数
    $@:所有参数
    
  • 산술 연산 과 할당
  • 常用的算术运算符号:
    	1、+   加
    	2、-   减
    	3、*   乘
    	4、/   除
    	5、**  次方
    	6、%   余数
    	
    算术运算格式:
    	1、let  VAR=算术运算表达式
    	2、VAR=$[算术运算表达式]
    	3、VAR=$((算术运算表达式))
    		# 给变量空间赋值时一定要使用 $[ ] 或者 $(( ))
    	4、VAR=$(expr $ARG1 $OP $ARG2)
    		# (): 括号内部是运行命令,直接取命令运行结果
    
    # 注意:乘法符号在有些场景中需要使用转义符。
    
    增强型赋值:
    	变量做某种算术运算后回存至此变量中,如下两种赋值方式表示同一个意思:
    		let i=$i+#
    		let i+=#
    	常用的增强型赋值:		
    		+=,-=,*=, /=, %=
    	
    	自增:
    		VAR=$[$VAR+1]
    		# 前面的 VAR 是变量空间,后面的 $VAR 是直接取变量空间里的值,注意区分
    			let  VAR+=1
    			let  VAR++
    						
    	自减:
    		VAR=$[$VAR-1]
    			let  VAR-=1
    			let  VAR--
    
    %(余数) 示例:
    root@LeeMumu:~# yushu=$((9%2))
    root@LeeMumu:~# echo $yushu
    1
    root@LeeMumu:~# yushu=$((8%2))
    root@LeeMumu:~# echo $yushu
    0
    

    셸 스 크 립 트
    1、什么是 shell 脚本?
    	1、shell 脚本是过程式编程,解释运行,依赖于外部程序文件运行。
    	2、shell 脚本是命令的堆积。
    # 很多命令不具有幂等性,需要用程序逻辑来判断运行条件是否满足,以避免其运行中发生错误。
    
    2、如何编写 shell 脚本?
    	脚本文件的第一行,顶格位置需要给出:
    		shebang,解释器路径,用于指明解释执行当前脚本的解释器程序文件。
    	常见的解释器:
    		#!/bin/bash
    		#!/usr/bin/python
    		#!/usr/bin/perl
    	同时,在脚本顶部还可以加入版本、作者和描述等信息,如下:	
    		#!/bin/bash
    		# Version: 0.0.1
    		# Author: LeeMumu
    		# Description: XXX
    
    3、如何运行 shell 脚本?
    	(1) 赋予执行权限,并直接运行此程序文件
    		chmod +x /PATH/TO/SCRIPT_FILE
    		source /PATH/TO/SCRIPT_FILE
    	(2) 直接运行解释器,将脚本以命令行参数传递给解释器程序
    		bash /PATH/TO/SCRIPT_FILE
    
    4、shell 脚本注意事项:
    	(1) 脚本中的空白行会被解释器忽略
    	(2) 脚本中,除了shebang,余下所有以#开头的行,都会被视作注释行而被忽略;此即为注释行
    	(3) shell 脚本的运行是通过运行一个子shell进程实现的
    

    스 크 립 트 의 조건 테스트
    条件测试:判断某需求是否满足,需要由测试机制来实现。
    		
    如何编写测试表达式以实现所需的测试:
    	(1) 执行命令,并利用命令状态返回值来判断;
    		0:成功
    		1-255:失败
    	(2) 测试表达式
    		test  EXPRESSION
    		[ EXPRESSION ]
    		[[ EXPRESSION ]]
    				
    # 注意:EXPRESSION两端必须有空白字符,否则为语法错误。
    

    bash 테스트 분류
    bash 的测试类型:
    	1、数值测试
    	2、字符串测试
    	3、文件测试
    	4、组合条件测试
    
  • 1. 수치 테스트
  • 数值测试:数值比较
    	-eq:是否等于     
    		# [ $num1 -eq $num2 ],注意空格
    	-ne:是否不等于
    	-gt:是否大于
    	-ge:是否大于等于
    	-lt:是否小于
    	-le:是否小于等于
    
    示例:
    root@LeeMumu:~# [ 2 -eq 2 ]            # 命令执行成功
    root@LeeMumu:~# echo $?
    0
    root@LeeMumu:~# [ 2 -gt 2 ]            # 命令执行失败
    root@LeeMumu:~# echo $?
    1
    
  • 2. 문자열 테스트
  • 字符串测试:
    	==:是否等于
    		# [ STRING1 == STRING2 ],注意空格
    	> :是否大于
    	< :是否小于
    	!=:是否不等于
    	=~:左侧字符串是否能够被右侧的PATTERN所匹配
    				
    	-z "STRING":判断指定的字串是否为空;空则为真,不空则假
    		# [[ -z “STRING” ]]
    	-n "STRING":判断指定的字符串是否不空;不空则真,空则为假			
    	# 注意:
    		(1) 字符串要加引用
    		(2) 要使用 [[ ]]				
    
    示例:
    root@LeeMumu:~# [ a == b ]             # 命令执行失败
    root@LeeMumu:~# echo $?
    1
    root@LeeMumu:~# [ aba == baa ]         # 命令执行失败
    root@LeeMumu:~# echo $?
    1
    root@LeeMumu:~# [ a == a ]             # 命令执行成功
    root@LeeMumu:~# echo $?
    0
    root@LeeMumu:~# [[ -z "" ]]            # 命令执行成功,字符串为空则为真
    root@LeeMumu:~# echo $?
    0
    root@LeeMumu:~# [[ -z "aaa" ]]         # 命令执行失败,字符串非空则为假
    root@LeeMumu:~# echo $?
    1
    
  • 3. 파일 테스트
  • 文件测试:
    1、存在性测试
    	-a  FILE
    	-e  FILE
    		文件的存在性测试,存在则为真,否则则为假
    
    2、存在性及类型测试
    	-b  FILE:是否存在并且为 块设备文件
    	-c  FILE:是否存在并且为 字符设备文件
    	-d  FILE:是否存在并且为 目录文件
    	-f  FILE:是否存在并且为 普通文件
    	-h  FILE:是否存在并且为 符号链接文件
    	-L  FILE:是否存在并且为 符号链接文件
    	-p  FILE:是否存在且为 命名管道文件
    	-S  FILE:是否存在且为 套接字文件
    
    3、文件权限测试:
    	-r  FILE:是否存在并且 对当前用户可读
    	-w  FILE:是否存在并且 对当前用户可写
    	-x  FILE:是否存在并且 对当前用户可执行
    
    4、特殊权限测试:
    	-u  FILE:是否存在并且 拥有suid权限
    	-g  FILE:是否存在并且 拥有sgid权限
    	-k  FILE:是否存在并且 拥有sticky权限
    				
    5、文件是否有内容:
    	-s  FILE:是否有内容,有内容为真,没内容为假
    				
    6、时间戳:
    	-N  FILE:文件自从上一次读操作后是否被修改过
    				
    7、从属关系测试:
    	-O  FILE:当前用户是否为文件的属主
    	-G  FILE:当前用户是否属于文件的属组
    
    8、双目测试:
    	FILE1  -ef  FILE2:FILE1与FILE2是否指向同一个文件系统的相同inode的硬链接;
    	FILE1  -nt  FILE2:FILE1是否新于FILE2,新为真,否则为假
    	FILE1  -ot  FILE2:FILE1是否旧于FILE2,旧为真,否则为假					
    
    示例:
    root@LeeMumu:~# touch space.txt            # 创建空文件
    root@LeeMumu:~# cat space.txt 
    root@LeeMumu:~# [[ -s space.txt ]]         # 有内容为真,没内容为假
    root@LeeMumu:~# echo $?
    1
    root@LeeMumu:~# echo 1 > space.txt 
    root@LeeMumu:~# [[ -s space.txt ]]
    root@LeeMumu:~# echo $?
    0
    root@LeeMumu:~# [[ -e space.backup.txt ]]   # 存在为真,不存在为假
    root@LeeMumu:~# echo $?
    1
    root@LeeMumu:~# touch space.backup.txt
    root@LeeMumu:~# [[ -e space.backup.txt ]]
    root@LeeMumu:~# echo $?
    0
    
  • 4. 조합 조건 테스트
  • 逻辑运算:
    第一种方式:
    	1、与运算:COMMAND1 && COMMAND2
    			# && 前面为真时, && 后面就继续执行
    			# && 前面为假时, && 后面就不执行
    	2、或运算:COMMAND1 || COMMAND2
    			# 常用于判断此用户是否存在,如果不存在就对用户进行添加。
    			# id user1 &> /dev/null || useradd user1
    			# || 前面为真时, || 后面就不执行
    			# || 前面为假时, || 后面就继续执行
    	3、非运算:! COMMAND 
    		
    	例如:
    		# [ -O FILE ] && [ -r FILE ]
    						
    第二种方式:
    	1、与运算:EXPRESSION1  -a  EXPRESSION2
    	2、或运算:EXPRESSION1  -o  EXPRESSION2
    	3、非运算:! EXPRESSION
    						
    	例如:
    		# [ -O FILE -a -x FILE ]
    
    示例:
    root@LeeMumu:~# [ 1 -eq 2 ] && echo 2
    root@LeeMumu:~# [ 1 -lt 2 ] && echo 2
    2
    root@LeeMumu:~# [ 1 -eq 2 ] || echo 2
    2
    root@LeeMumu:~# [ 1 -lt 2 ] || echo 2
    

    스 크 립 트 상태 반환 값
    脚本的状态返回值:默认是脚本中执行的最后一条件命令的状态返回值。
    
    可用如下命令自定义状态退出状态码
    	# exit [n]:n为指定的状态码,一般制定为 1~255 结束脚本执行。
    
    注意:shell进程遇到exit时,即会终止,因此,整个脚本执行即为结束。
    

    스 크 립 트 문법 검사 및 디 버 깅 실행
    1、检测脚本中的语法错误:
    	# bash -n /path/to/some_script
    		
    2、对脚本进行调试执行:
    	# bash -x /path/to/some_script
    

    프로 그래 밍 스 크 립 트 의 사용자 상호작용
    사용자 가 대화 할 때 read 명령 을 사용 합 니 다.이 명령 은 키보드 에서 변 수 를 읽 는 값 으로 셸 스 크 립 트 에서 사용자 와 대화 하 는 장소 에 사 용 됩 니 다.이 명령 은 한 번 에 여러 변수의 값 을 읽 을 수 있 으 며, 변수 와 입력 한 값 은 모두 빈 칸 으로 분리 해 야 합 니 다.
    메모: 사용자 가 상호작용 을 하 는 과정 에서 입력 한 내용 을 삭제 하려 면 Ctrl + Delete 조합 키 를 동시에 사용 해 야 합 니 다.
    read:从键盘读取变量值
    
    使用格式:
    read  [option]... [name ...]
    	-p 'PROMPT'              # 指定读取值时的提示符
    	-t TIMEOUT               # 指定读取值时等待的时间(秒)
    
    示例:
    root@LeeMumu:~# cat read.sh 
    #!/bin/bash
    #
    read -p "Please input what you want:" aBa    # 输入的信息赋值给了变量 aBa
    echo "You input the $aBa!"
    root@LeeMumu:~# ./read.sh 
    Please input what you want:This is a new line
    You input the This is a new line!
    

    스 크 립 트 실행 방식
    셸 스 크 립 트 는 프로 세 스 프로 그래 밍 언어 로 코드 의 실행 순 서 는 다음 과 같 습 니 다.
    1、顺序执行
    	# 逐条运行脚本代码
    	
    2、选择执行
    	# 代码有一个分支:条件满足时才会执行
    	# 两个或以上的分支:只会执行其中一个满足条件的分支
    	
    3、循环执行
    	# 代码片断(循环体)要执行0、1或多个来回
    

    1. 실행 선택
    if 구문
    单分支的if语句 格式:
    if  测试条件
    then
    	代码分支
    fi
    
    双分支的if语句 格式:
    if  测试条件; then
    	条件为真时执行的分支
    else
    	条件为假时执行的分支
    fi
    
    多分支的if语句
    if  CONDITION1; then
    	条件1为真 分支
    elif  CONDITION2; then
    	条件2为真 分支
    elif  CONDITION3; then
    	条件3为真 分支
    	... ...
    elif  CONDITIONn; then
    	条件n为真 分支
    else
    	所有条件均不满足时的分支
    fi
    
    注意:即便多个条件可能同时都能满足,分支只会执行中其中一个,首先测试为“真”的条件。
    

    case 구문
    语法格式:
    case  $VARAIBLE  in  
    PAT1)
    	分支1
    	;;
    PAT2)
    	分支2
    	;;
    	...
    *)
    	分支n
    	;;
    esac
    
    对如上 case 语法格式进行说明:
    	# case                 关键字
    	# in                   关键字
    	# PAT1)                仅支持 glob 风格的通配符号
    	# VARDIBLE             变量
    	# *)                  相当于 else
    	# esac                 结束关键字(与 case 相反)
    	# ;;                   双分号
    	# 适用于变量值同多个字符串进行等值或不等值比较的情形,仅能替代部分多分支 if 语句
    
    # case 支持 glob 风格的通配符
    	*            # 任意长度的任意字符;
    	?            # 任意单个字符;
        []           # 范围内任意单个字符;
    	a|b          # a或b			
    

    예시: 서비스 프레임 워 크 스 크 립 트 를 작성 합 니 다.요 구 는 다음 과 같 습 니 다.
    $lockfile,  值/var/lock/subsys/SCRIPT_NAME
    				
    (1) 此脚本可接受start, stop, restart, status四个参数之一;
    (2) 如果参数非此四者,则提示使用帮助后退出;
    (3) start,则创建lockfile,并显示启动;
    	stop,则删除lockfile,并显示停止;
    	restart,则先删除此文件再创建此文件,而后显示重启完成;
    	status,如果lockfile存在,则显示running,否则,则显示为stopped。				
    
    脚本如下:
    #!/bin/bash
    #
    # chkconfig: - 50 50
    # description: test service script
    #
    prog=$(basename $0)
    lockfile=/var/lock/subsys/$prog
    
    case $1  in
    start)
    	if [ -f $lockfile ]; then
    		echo "$prog is running yet."
    	else
    		touch $lockfile
    		[ $? -eq 0 ] && echo "start $prog finshed."
    	fi
    	;;
    stop)
    	if [ -f $lockfile ]; then
    		rm -f $lockfile
    		[ $? -eq 0 ] && echo "stop $prog finished."
    	else
    		echo "$prog is not running."
    	fi
    	;;
    restart)
    	if [ -f $lockfile ]; then
    		rm -f $lockfile
    		touch $lockfile
    		echo "restart $prog finished."
    	else
    		touch -f $lockfile
    		echo "start $prog finished."
    	fi
    	;;
    status)
    	if [ -f $lockfile ]; then
    		echo "$prog is running"
    	else
    		echo "$prog is stopped."
    	fi
    	;;
    *)
    	echo "Usage: $prog {start|stop|restart|status}"
    		exit 1
    esac
    
    命令执行:
    # cp testservice /etc/init.d/
    # chkconfig --add testservice
    # chkconfig --list testservice
    # service testservice start
    # ls /var/lock/subsys/             # 启动服务后都会在这个目录下进行文件创建
    

    2. 반복 실행
    循环执行:是指将一段代码重复执行0、1或多次。
    	进入条件:条件满足时才进入循环。
    	退出条件:每个循环都应该有退出条件,以有机会退出循环。
    
    循环分为三种:
    	1、for循环
    	2、while循环
    	3、until循环
    
    进入条件:
    	for:列表元素非空
    	while:条件测试结果为“真”
    	unitl:条件测试结果为“假”
    退出条件:
    	for:列表元素遍历完成
    	while:条件测试结果为“假”
    	until:条件测试结果为“真”
    
    循环控制语句:
    # continue:提前结束本轮循环,不会执行后面的命令,直接进入下一轮循环判断。
    while  CONDITION1; do
    	CMD1
    	...
    	if  CONDITION2; then
    		continue
    	fi
    	CMDn
    	...
    done
    
    # break:提前跳出循环
    while  CONDITION1; do
    	CMD1
    	...
    	if  CONDITION2; then
    		break
    	fi
    done
    
    创建死循环:
    while true; do
    	循环体
    done
    退出方式:
    	某个测试条件满足时,让循环体执行break命令。
    
    示例:求100以内所有偶数之和;										
    #!/bin/bash
    #
    declare -i evensum=0
    declare -i i=0
    
    while [ $i -le 100 ]; do
    	let i++
    	if [ $[$i%2] -eq 1 ]; then
    		continue
    	fi
    	let evensum+=$i
    done
    
    echo "Even sum: $evensum"
    
    示例:求100以内所奇数之和
    #!/bin/bash
    #
    declare -i oddsum=0
    declare -i i=1
    
    while true; do
    	let oddsum+=$i
    	let i+=2
    	if [ $i -gt 100 ]; then
    		break
    	fi
    done
    

    sleep 명령 설명:
    sleep 命令:
    	- delay for a specified amount of time
    	
    命令格式:		
    # sleep NUMBER
    

    sleep 예제: 로그 인 한 사용자 의 정 보 를 3 초 간격 으로 시스템 에 가 져 옵 니 다.이 중 logstash 사용자 가 시스템 에 로그 인 하면 로그 에 기록 하고 종료 합 니 다.
    #!/bin/bash
    #
    while true; do
    	if who | grep "^logstash\>" &> /dev/null; then
    		break
    	fi
    	sleep 3
    done
    
    echo "$(date +"%F %T") logstash logged on" >> /tmp/users.log	
    				
    #!/bin/bash
    #
    until who | grep "^logstash\>" &> /dev/null; do
    	sleep 3
    done
    
    echo "$(date +"%F %T") logstash logged on" >> /tmp/users.log	
    

    2.1 for circle
    for 循环包括以下两种
    	1、遍历列表
    	2、控制变量
    
    遍历列表:
    
    语法格式:
    for  VARAIBLE  in  LIST; do
    	循环体
    done
    
    参数解释:
    1、for 是 关键字
    2、VARAIBLE 是 变量 
    3、in 是 关健字
    4、LIST 是 赋值列表
    5、do 和 done 是 关键字
    
    VARAIBLE 赋值的三种形式:
    	1、VARAIBLE = VALUE
    	2、read 语句
    	3、for 语句
    
    进入和退出条件:
    	1、进入条件:只要列表有元素,即可进入循环
    	2、退出条件:列表中的元素遍历完成
    

    LIST 목록 생 성 방법
    일반적으로 다음 과 같은 다섯 가지 가 있다.
  • 1. 직접 드 리 겠 습 니 다
  • root@LeeMumu:~# echo 1 2 3 4 5 
    1 2 3 4 5
    
  • 2. 정수 목록
  • (1)、{start..end}
    root@LeeMumu:~# echo {1..5}
    1 2 3 4 5
    
    (2)、seq [start  [incremtal]]  last      # 中间参数是 步长
    root@LeeMumu:~# seq 1 3
    1
    2
    3
    root@LeeMumu:~# seq 3
    1
    2
    3
    root@LeeMumu:~# seq 3 3 9
    3
    6
    9
    
  • 3. 목록 매개 변 수 를 되 돌려 줍 니 다
  • ls:返回列表 一行一个
    cat:查看文件的返回列表参数
    
    # 只要结果能输出字串的
    
  • 4、glob
  • 匹配符合条件的列表:
    # ls -d /etc/p*
    
  • 5. 변수 인용
  • $@ :参数传递
    $* :参数传递
    
    root@LeeMumu:~# passwd_Lines=`wc -l /etc/passwd | cut -d' ' -f1`  
    	# 注意:以上命令是 反引号,作命令引用
    root@LeeMumu:~# echo $passwd_Lines
    33
    root@LeeMumu:~# seq 1 $passwd_Lines
    1
    2
    ...
    32
    33
    root@LeeMumu:~#  echo {1.."$passwd_Lines"}
    {1..33}
    	# 注意:使用花括号时引用变量时,不会生效,可用 seq
    root@LeeMumu:~# echo {1..$passwd_Lines}
    {1..33}
    root@LeeMumu:~# echo {1..33}
    1 2 3 4 5 6 ... ...  32 33
    root@LeeMumu:~# echo '$passwd_Lines'
    $passwd_Lines
    

    for 순환 예시
    1. 100 이내 의 정수 합 을 구한다.
    #!/bin/bash
    #
    declare -i sum=0
    
    for i in {1..100}; do
    	echo "\$sum is $sum, \$i is $i"
    	sum=$[$sum+$i]
    done
    
    echo $sum
    

    2. 판단/var/log 디 렉 터 리 에 있 는 모든 파일 의 내용 형식 입 니 다.
    #!/bin/bash
    #
    for filename in /var/log/*; do
    	if [ -f $filename ]; then
    		echo "Common file."
    	elif [ -d $filename ]; then
    		echo "Directory."
    	elif [ -L $filename ]; then
    		echo "Symbolic link."
    	elif [ -b $filename ]; then
    		echo "block special file."
    	elif [ -c $filename ]; then
    		echo "character special file."
    	elif [ -S $filename ]; then
    		echo "Socket file."
    	else
    		echo "Unkown."
    	fi					
    done				
    

    3. 구구 곱셈 표 인쇄
    #外循环控制乘数,内循环控制被乘数;
    #!/bin/bash
    #
    for j in {1..9}; do
    	for i in $(seq 1 $j); do
    		echo -n -e "${i}X${j}=$[${i}*${j}]\t"
    	done
    	echo 
    done
    

    for 순환 의 특수 용법
    语法格式;
    for  ((控制变量初始化;条件判断表达式;控制变量的修正语句)); do
    	循环体
    done
    
    控制变量初始化:仅在循环代码开始运行时执行一次
    控制变量的修正语句:每轮循环结束会先进行控制变量修正运算,而后再做条件判断
    
    示例:求100以内所有正整数之和
    #!/bin/bash
    #
    declare -i sum=0
    
    for ((i=1;i<=100;i++)); do
    	let sum+=$i
    done
    
    echo "Sum: $sum."
    
    				
    示例:打印九九乘法表
    #!/bin/bash
    #
    for ((j=1;j<=9;j++)); do
    	for ((i=1;i<=j;i++)); do
    		echo -e -n "${i}X${j}=$[${i}*${j}]\t"
    	done
    	echo
    done
    

    2.2 while 순환
    语法格式:
    while  CONDITION; do
    	循环体
    	循环控制变量修正表达式
    done
    
    进入条件:CONDITION测试为 真
    退出条件:CONDITION测试为 假	
    
    示例:求100以内的正整数之和
    #!/bin/bash
    #
    declare -i sum=0
    declare -i i=1
    
    while [ $i -le 100 ]; do
    	let sum+=$i
    	let i++
    done
    
    echo $sum
    
  • while 순환 의 특수 용법 (파일 을 옮 겨 다 니 는 줄):
  • while  read  VARIABLE; do
    	循环体;
    done  <  /PATH/FROM/SOMEFILE
    
    # 依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将基赋值给VARIABLE变量
    
    示例:找出ID号为偶数的用户,显示其用户名、ID及默认shell
    #!/bin/bash
    #
    while read line; do
    	userid=$(echo $line | cut -d: -f3)
    	username=$(echo $line | cut -d: -f1)
    	usershell=$(echo $line | cut -d: -f7)
    
    	if [ $[$userid%2] -eq 0 ]; then
    		echo "$username, $userid, $usershell."
    	fi
    done < /etc/passwd	
    

    2.3 순환 까지
    until  CONDITION; do
    	循环体
    	循环控制变量修正表达式
    done
    		
    进入条件:CONDITION测试为 假
    退出条件:CONDITION测试为 真		
    
    示例:求100以内的正整数之和
    #!/bin/bash
    #
    declare -i sum=0
    declare -i i=1
    
    until [ $i -gt 100 ]; do
    	let sum+=$i
    	let i++
    done
    
    echo $sum
    

    스 크 립 트 예제
    1. vim 는 네 개의 문 자 를 자동 으로 들 여 쓰 는 방법 을 설정 합 니 다.
    vim 的配置文件是:/etc/vimrc 
    可以对此配置文件进行编辑,添加配置: set tabstop=4 ,重读配置,使文件生效即可。
    
    如下:
    [root@LeeMumu ~]# vi /etc/vimrc        # 编辑 vim 的配置文件
    set tabstop=4
    [root@LeeMumu ~]# source /etc/vimrc    # 重读配置文件。使文件生效
    

    2. 세 사용 자 를 자동 으로 추가 하고 이 세 사용자 의 uid 의 합 을 계산 합 니 다.
    [root@LeeMumu ~]# ./sUMID.sh
    Add user user21 successfully.
    The user user21 ID is:1004. 
    Add user user22 successfully.
    The user user22 ID is:1005. 
    Add user user33 successfully.
    The user user33 ID is:1006. 
    The sum of these UserID is:3015.
    [root@LeeMumu ~]# tail -n 3 /etc/passwd
    user21:x:1004:1017::/home/user21:/bin/bash
    user22:x:1005:1018::/home/user22:/bin/bash
    user33:x:1006:1019::/home/user33:/bin/bash
    [root@LeeMumu ~]# cat sUMID.sh 
    #!/bin/bash
    #
    declare -i sum=0
    
    for i in user21 user22 user33; do
    	if id $i &> /dev/null ; then
    		echo "The user $i exists."
    	else
    		useradd $i
    		echo "Add user $i successfully."
    	fi
    	ID=`grep "^$i" /etc/passwd | cut -d":" -f3`
    #   ID=$(grep "^$i" /etc/passwd | cut -d":" -f3)           # 用 $() 或 `` 都可以
    	echo "The user $i ID is:$ID. "
    	sum=$[$sum+$ID]
    done
    
    	echo "The sum of these UserID is:$sum."
    

    3. 명령 을 통 해 두 텍스트 파일 경 로 를 스 크 립 트 에 전달 하고 빈 줄 의 합 을 계산 합 니 다.
    #!/bin/bash
    #
    file1_lines=$(grep "^$" $1 | wc -l)
    file2_lines=$(grep "^$" $2 | wc -l)
    
    echo "Total blank lines: $[$file1_lines+$file2_lines]"	
    

    4. 매개 변 수 를 통 해 스 크 립 트 에 사용자 이름 을 전달 합 니 다. 이 사용자 가 저장 하지 않 을 때 추가 합 니 다.
    第一种:
    #!/bin/bash
    #
    if ! grep "^$1\>" /etc/passwd &> /dev/null; then
    	useradd $1
    	echo $1 | passwd --stdin $1 &> /dev/null
    	echo "Add user $1 finished."
    fi	
    
    第二种:			
    #!/bin/bash
    #
    if [ $# -lt 1 ]; then
    	echo "At least one username."
    	exit 2
    fi
    
    if ! grep "^$1\>" /etc/passwd &> /dev/null; then
    	useradd $1
    	echo $1 | passwd --stdin $1 &> /dev/null
    	echo "Add user $1 finished."
    fi		
    
    第三种:			
    #!/bin/bash
    #
    if [ $# -lt 1 ]; then
    	echo "At least one username."
    	exit 2
    fi
    
    if grep "^$1\>" /etc/passwd &> /dev/null; then
    	echo "User $1 exists."
    else
    	useradd $1
    	echo $1 | passwd --stdin $1 &> /dev/null
    	echo "Add user $1 finished."
    fi			
    

    5. 명령 행 매개 변 수 를 통 해 두 개의 숫자 를 지정 하고 그 중에서 비교적 큰 수 치 를 출력 합 니 다.
    第一种:
    #!/bin/bash
    #
    if [ $# -lt 2 ]; then
    	echo "Two integers."
    	exit 2
    fi
    
    if [ $1 -ge $2 ]; then
    	echo "Max number: $1."
    else
    	echo "Max number: $2."
    fi
    
    第二种:(相对于第一种来说,第二种是代码优化)
    #!/bin/bash
    #
    if [ $# -lt 2 ]; then
    	echo "Two integers."
    	exit 2
    fi
    
    declare -i max=$1
    
    if [ $1 -lt $2 ]; then
    	max=$2
    fi
    
    echo "Max number: $max."
    
    第三种:(if 语句可嵌套)
    #!/bin/bash
    #
    if [ $# -lt 2 ]; then
    	echo "TWO INTEGERS!"
    	exit 1
    else
    	if [ $1 -lt $2 ]; then
    		echo "The $2 is bigger than $1."
    	elif [ $1 -eq $2 ]; then
    		echo "The $1 is equal than $1."
    	else
    		echo "The $1 is bigger than $1."
    	fi
    fi 
    

    6. 스 크 립 트 매개 변 수 는 스 크 립 트 에 파일 경 로 를 전달 하여 이 파일 의 종 류 를 판단 합 니 다.
    #!/bin/bash
    #
    if [ $# -lt 1 ]; then
    	echo "At least on path."
    	exit 1
    fi
    
    if ! [ -e $1 ]; then
    	echo "No such file."
    	exit 2
    fi
    
    if [ -f $1 ]; then
    	echo "Common file."
    elif [ -d $1 ]; then
    	echo "Directory."
    elif [ -L $1 ]; then
    	echo "Symbolic link."
    elif [ -b $1 ]; then
    	echo "block special file."
    elif [ -c $1 ]; then
    	echo "character special file."
    elif [ -S $1 ]; then
    	echo "Socket file."
    else
    	echo "Unkown."
    fi	
    

    7. 스 크 립 트 에 매개 변 수 를 전달 합 니 다. 이 매개 변 수 는 사용자 이름 입 니 다.ID 번호 에 따라 사용자 유형 을 판단 합 니 다.
    (0: 관리자, 1 - 999: 시스템 사용자, 1000 +: 로그 인 사용자)
    #!/bin/bash
    #
    [ $# -lt 1 ] && echo "At least on user name." && exit 1
    
    ! id $1 &> /dev/null && echo "No such user." && exit 2
    
    userid=$(id -u $1)
    
    if [ $userid -eq 0 ]; then
    	echo "root"
    elif [ $userid -ge 1000 ]; then
    	echo "login user."
    else
    	echo "System user."
    fi	
    

    8. 스 크 립 트 를 작성 할 때 다음 과 같이 요구 합 니 다.
    (1) 列出如下菜单给用户:
    disk) show disks info;
    mem) show memory info;
    cpu) show cpu info;
    *) quit;
    (2) 提示用户给出自己的选择,而后显示对应其选择的相应系统信息。
    
    #!/bin/bash
    #
    cat << EOF
    cpu) display cpu information
    mem) display memory infomation
    disk) display disks information
    quit) quit
    ===============================
    EOF
    
    read -p "Enter your option: " option
    
    while [ "$option" != "cpu" -a "$option" != "mem" -a "$option" != "disk" -a "$option" != "quit" ]; do
    	echo "cpu, mem, disk, quit"
    	read -p "Enter your option again: " option
    done
    
    if [ "$option" == "cpu" ]; then
    	lscpu
    elif [ "$option" == "mem" ]; then
    	free -m
    elif [ "$option" == "disk" ]; then
    	fdisk -l /dev/[hs]d[a-z]
    else
    	echo "quit"
    	exit 0
    fi
    

    9. 각각 100 이내 의 모든 짝수 의 합 과 모든 홀수 의 합 을 구한다.
    第一个脚本:
    #!/bin/bash
    #计算100以内所有奇数的和以及所有偶数的和;分别显示之
    #奇数和变量
    let SUM1=0
    #偶数和变量
    let SUM2=0
    for I in {1..100}; do
    	if [ $[$I%2] -eq 0 ]; then
    		SUM1=$[$SUM1+$I]
    	else
    		SUM2=$[$SUM2+$I]
    	fi
    done
    
    echo -e "SUM1=$SUM1
    SUM2=$SUM2" 第二个脚本: #!/bin/bash # declare -i even=0 declare -i odd=0 for i in {1..100}; do if [ $[$i%2] -eq 0 ]; then even=$[$even+$i] else odd=$[$odd+$i] fi done echo "The sum of the even_number between 1 and 100 is: $even" echo "The sum of the odd_number between 1 and 100 is: $odd" echo "The sum of the integer between 1 and 100 is: $[$even+$odd]"

    10. 현재 시스템 에 사용 되 는 모든 id 의 합 을 계산 합 니 다.
    #!/bin/bash
    #
    
    declare -i passwd_Lines=`wc -l /etc/passwd | cut -d' ' -f1`
    declare -i sum_UID=0
    
    for i in `cat /etc/passwd | cut -d':' -f3`; do
    	sum_UID=$[$sum_UID+$i]
    done
    
    echo "The sum of the user-ID is:$sum_UID"
    

    11. 스 크 립 트 매개 변 수 를 통 해 스 크 립 트 에 디 렉 터 리 를 전달 한 다음 에 이 디 렉 터 리 에 있 는 모든 텍스트 파일 의 줄 수 를 계산 합 니 다.이 파일 의 총 수 를 설명 합 니 다.
    #!/bin/bash
    #
    
    declare -i count=0
    declare -i line_count=0
    
    if [ $# -eq 1 ];then
    	if [ -d $1 ]; then
    		for filename in $1* ;do
    			if [ -f $filename ];then
    				line_count=$[$line_count+`wc -l $filename | cut -d' ' -f1`]
    				count=$[$count+1]
    				echo "The Common_File $filename has $line_count lines."
    			else
    				exit 1
    			fi
    		done
    	else 
    		echo -e "Please Input Correct Directory.
    For Example: /path/path/" exit 2 fi else echo "Please Input One Directory!" exit 3 fi echo " " echo "The Number of Common_File is:$count" echo "The Total Lines of Common_File is:$line_count"

    12. 계산/etc/passwd 파일 의 10 번 째 사용자 와 20 번 째 사용자 의 id 번호 의 합.
    [root@LeeMumu ~]# bash sum1020.sh 
    The UID OF the tenth user is: 11.
    The UID OF the twentith user is: 59.
    The UID_SUM OF the tenth user and the twentith user is: 70.
    [root@LeeMumu ~]# cat sum1020.sh
    #!/bin/bash
    #
    ID10=$(head -10 /etc/passwd | tail -1 | cut -d":" -f3)
    ID20=$(head -20 /etc/passwd | tail -1 | cut -d":" -f3)
    
    sum1020=$[$ID10+$ID20]
    
    echo "The UID OF the tenth user is: $ID10."
    echo "The UID OF the twentith user is: $ID20."
    echo "The UID_SUM OF the tenth user and the twentith user is: $sum1020."
    

    13./etc/rc. d/init. d/functions 와/etc/inittab 파일 의 공백 줄 수 를 계산 합 니 다.
    [root@LeeMumu ~]# bash sumSPACElines.sh 
    The /etc/rc.d/init.d/functions has 91 space-lines.
    The /etc/inittab has 0 space-lines.
    The /etc/rc.d/init.d/functions and /etc/inittab totally have 91 space-lines.
    [root@LeeMumu ~]# cat sumSPACElines.sh
    #!/bin/bash
    #
    ID10=$(grep "^[[:space:]]*$"   /etc/rc.d/init.d/functions | wc -l)
    ID20=$(grep "^[[:space:]]*$"   /etc/inittab | wc -l)
    
    sum1020=$[$ID10+$ID20]
    
    echo "The /etc/rc.d/init.d/functions has $ID10 space-lines."
    echo "The /etc/inittab has $ID20 space-lines."
    echo "The /etc/rc.d/init.d/functions and /etc/inittab totally have $sum1020 space-lines."
    

    14. 스 크 립 트 를 작성 하여 172.16.141. X 네트워크 에서 어떤 호스트 주소 가 사용 되 고 사용 되 지 않 았 는 지 찾 아 결 과 를 해당 파일 에 저장 합 니 다.
    [root@LEEMUMU ~]# cat ping.sh 
    #!/bin/bash
    #
    
    declare -i upnum=0
    declare -i downnum=0
    declare -i i=1
    
    pinghost() {
    	if ping $1 -c 1 -W 1 &>/dev/null; then
    		echo -e "\033[1;32m$1 is up.\033[0m"  | tee -a up20190717.txt
    		upnum=$[$upnum+1]
    	else
    		echo -e "\033[1;31m$1 is down.\033[0m"  | tee -a down20190717.txt
    		downnum=$[$downnum+1]
    	fi
    	
    }
    
    while [ $i -le 254 ]; do
    	pinghost 172.16.141.$i
    	let i++
    done
    
    echo "Uphost is $upnum."
    echo "Downhost is $downnum."
    

    15. 스 크 립 트 를 작성 하여 실현: C 류, B 류 또는 A 류 네트워크 의 모든 호스트 가 온라인 인지 확인 할 수 있 습 니 다.
    #!/bin/bash
    #
    
    cping() {
    local i=1
    while [ $i -le 5 ]; do
    	if ping -W 1 -c 1 $1.$i &> /dev/null; then
    		echo "$1.$i is up"
    	else
    		echo "$1.$i is down."
    	fi
    	let i++
    done
    }
    
    bping() {
    local j=0
    while [ $j -le 5 ]; do
    	cping $1.$j
    	let j++
    done
    }
    
    aping() {
    local x=0
    while [ $x -le 255 ]; do
    	bping $1.$x
    	let x++
    done
    }
    

    16. 스 크 립 트 를 작성 하고 명령 행 매개 변 수 를 통 해 사용자 이름 을 입력 하여 ID 가 짝수 인지 홀수 인지 판단 합 니 다.
    [root@LeeMumu ~]# ./evenorodd.sh 
    Please Input One UserName:JC9
    The UserID Of JC9 is even!
    [root@LeeMumu ~]# ./evenorodd.sh
    Please Input One UserName:jc8
    The jc8 Not Exist!
    Please Input Another UserName!
    [root@LeeMumu ~]# ./evenorodd.sh
    Please Input One UserName:JC6
    The UserID Of JC6 is odd!
    
    [root@LeeMumu ~]# cat evenorodd.sh 
    #!/bin/bash
    #
    read -p "Please Input One UserName:" UserName
    
    if ! id $UserName &> /dev/null; then
    	echo -e "\e[1;31mThe $UserName Not Exist!\e[0m"
    	echo -e "\e[1;32mPlease Input Another UserName!\e[0m"
    	exit 1
    else
    	if [ $[`id -u $UserName`%2] -eq 0 ];then
    		echo -e "\e[1;33mThe UserID Of $UserName is even!\e[0m"
    	else	
    		echo -e "\e[1;34mThe UserID Of $UserName is odd!\e[0m"
    	fi
    fi
    

    17. 각각 while, for 순환 으로 10.0.0.1/24 네트워크 에 존재 하 는 IP 주 소 를 검사 합 니 다.
    첫 번 째 종류:
    #!/bin/bash
    # 先定义函数,再引用函数
    while_ping(){
        local i=1
        while [ $i -le 255 ];do
        ping -W 1 -c 1 $1.$i &> /dev/null
            if [ $? == 0 ];then
                echo "$1.$i is up"
            else
                echo "$1.$i is down"
            fi
            let i++
        done
    }
    
    ########################################################
    
    for_ping(){
    
        for i in {1..255};do
        ping -W 1 -c 1 $1.$i &> /dev/null
            if [ $? == 0 ];then
                echo "$1.$i is up"
            else
                echo "$1.$i is down"
            fi
        done
    }
    
    ########################################################
    
    if [ $# -lt 2 ];then
        echo "Usage sh $0 {for_ping|while_ping} Network"
        echo "Such as :for_ping 192.168.1 OR while_ping 192.168.1"
        exit 1
    elif [[ $1 == "for_ping" ]];then
        echo "for_ping"
        for_ping $2
    elif [[ $1 == "while_ping" ]];then
        echo "while_ping"
        while_ping $2
    fi
    

    두 번 째:
    #!/bin/bash
    for ip in {1..255};do
    	ping -c 1 10.0.0.$ip > /dev/null 2>&1
    	if [ $? -eq 0 ]; then
    		echo 10.0.0.$ip is UP
    	else
    		echo 10.0.0.$ip is DOWN
    	fi
    done
    
    ##############################################
    
    declare -i ip=1
    while [ $ip -le 255 ]; do
        ping -c 1 10.0.0.$ip > /dev/null 2>&1
        if [ $? -eq 0 ]; then
            echo 10.0.0.$ip UP
        else
            echo 10.0.0.$ip DOWN
        fi
        let ip++
    done
    

    좋은 웹페이지 즐겨찾기