Shell编程之函数

一、Shell函数

1.概念与作用

将程序里多次被调用的相同代码组合起来(函数体),并为其取一个名字(函数名),其他所有想重复调用这部分代码的地方都只需调用这个名字即可。

优势:

  • 把相同的程序段定义成函数,减少代码量,提高开发效率
  • 增加程序的可读性、易读性,提升管路效率
  • 可以实现程序功能模块化,使程序具备通用性

2.函数语法

写法一:
function 函数名() {
	指令
	return n
}

写法二:
function 函数名 {
	指令
	return n
}

写法三:
函数名() {
	指令
	return n
}

3.函数的执行

(1)不带参数的函数
直接输入函数名即可(不带小括号)
注意:

  • 执行时,function和小括号都不要带
  • 函数的定义或加载必须在执行之前
  • 执行顺序:系统别名-函数-系统命令-可执行文件
  • 函数执行时,会与脚本共用变量,也可以设定局部变量
  • return命令的功能与exit类似,是退出函数,而exit是退出脚本
  • return语句会返回一个退出值给调用函数的当前程序,而exit会返回给执行程序的当前Shell
  • 若将函数放在单独文件中,在被脚本加载时,需使用source或 . 来加载
  • 在函数内一般使用local定义局部变量

(2)带参数的函数
函数名 参数1 参数2
注意:

  • 位置参数($1、$2...$#、$*、$?、$@)都可以作为函数的参数使用
  • 父脚本的参数临时被函数参数所遮盖或隐藏
  • $0比较特殊,它仍是父脚本的名称
  • 当函数执行完时,原来的命令行脚本的参数即可恢复
  • 函数的参数变量是在函数体里面定义的

4.函数基础实践

(1)建立两个简单的函数并调用执行

[root@codis-178 ~]# cat 8_1.sh 
#!/bin/bash

oldboy(){
	echo "I am oldboy."
}

function oldgirl(){
	echo "I am oldgirl."
}
oldboy
oldgirl
[root@codis-178 ~]# sh 8_1.sh 
I am oldboy.
I am oldgirl.

(2)分离函数体和执行函数脚本

[root@codis-178 ~]# cat >> /root/8_2.sh<<- EOF
> oldboy(){
>     echo "I am oldboy."
> }
> EOF
[root@codis-178 ~]# cat 8_2.sh 
oldboy(){
    echo "I am oldboy."
}
[root@codis-178 ~]# cat 8_3.sh 
#!/bin/bash
[ -f /root/8_2.sh ] && . /root/8_2.sh || exit 1
oldboy
[root@codis-178 ~]# sh 8_3.sh 
I am oldboy.

(3)带参数的函数

[root@codis-178 ~]# cat 8_2.sh 
oldboy(){
    echo "I am oldboy.you are $1"
}
[root@codis-178 ~]# cat 8_4.sh 
#!/bin/bash
[ -f /root/8_2.sh ] && . /root/8_2.sh || exit 1
oldboy xiaoda
[root@codis-178 ~]# sh 8_4.sh 
I am oldboy.you are xiaoda

(4)将函数的传参转换成脚本文件命令传参

[root@codis-178 ~]# cat 8_2.sh 
oldboy(){
    echo "I am oldboy.you are $1"
}
[root@codis-178 ~]# cat 8_4.sh 
#!/bin/bash
[ -f /root/8_2.sh ] && . /root/8_2.sh || exit 1
oldboy $1
[root@codis-178 ~]# sh 8_4.sh xiaoda
I am oldboy.you are xiaoda

5.利用函数开发企业及URL检测脚本

[root@codis-178 ~]# cat 8_5.sh 
#!/bin/bash
function usage(){
	echo $"usage:$0 url"
	exit 1
}

function check_url(){
	wget --spider -q -o /dev/null --tries=1 -T 5 $1
	if [ $? -eq 0 ]
		then
			echo "$1 is yes."
	else
		echo "$1 is no."
	fi
}

function main(){
	if [ $# -ne 1 ]   #传入多个参数,打印帮助函数
		then
			usage
	fi
	check_url $1
}
main $*    # 将命令行接收的所有参数传给函数
[root@codis-178 ~]# sh 8_5.sh 
usage:8_5.sh url
[root@codis-178 ~]# sh 8_5.sh www.baidu.com
www.baidu.com is yes.
[root@codis-178 ~]# sh 8_5.sh www.163.163.com
www.163.163.com is no.

牛逼写法

[root@codis-178 ~]# cat 8_5_1.sh 
#!/bin/bash
. /etc/init.d/functions  #引入系统函数库
function usage(){
	echo $"usage:$0 url"
	exit 1
}

function check_url(){
	wget --spider -q -o /dev/null --tries=1 -T 5 $1
	if [ $? -eq 0 ]
		then
			action "$1 is yes." /bin/true
	else
		action "$1 is no." /bin/false
	fi
}

function main(){
	if [ $# -ne 1 ]
		then
			usage
	fi
	check_url $1
}
main $*
[root@codis-178 ~]# sh 8_5_1.sh www.anzhi.com
www.anzhi.com is yes.                                      [  OK  ]
[root@codis-178 ~]# sh 8_5_1.sh www.bbaidu.com
www.bbaidu.com is no.                                      [FAILED]

6.开发一键优化系统脚本

思路:

  • 配置yum源
  • 禁用开机不需要的启动脚本
  • 优化内核参数
  • 增加系统文件描述符、堆栈等配置
  • 禁止root远程登录,修改SSH端口,禁止DNS及空密码
  • 有外网IP的机器需要开启、配置防火墙,关闭SELinux
  • 清除无用的默认系统账户和组,添加运维成员
  • 锁定敏感文件,如/etc/passwd
  • 配置时间同步
  • 初始化用户,配置sudo权限控制
  • 修改系统字符集
  • 修补漏洞
[root@codis-178 ~]# cat sys_opt.sh
#!/bin/bash
# author:tongxiaoda

# set env
export PATH=$PATH:/bin:/sbin:/usr/sbin

# Require root to run this script
if [ "$UID" != "0" ];then
	echo "Please run this script by root."
	exit 1
fi

# define cmd var
SERVICE=`which service`
CHKCONFIG=`which chkconfig`

function mod_yum(){
	# modify yum path
	if [ -e /etc/yum.repos.d/centos6.7 ]
		then
			mv /data/soft/centos6.7 /etc/yum.repos.d/
	fi
}

function close_selinux(){
	#1.close selinux
	sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
	setenforce 0 &>/dev/null
}

function close_iptables(){
	#2.close iptables
	/etc/init.d.iptables stop
	/etc/init.d iptables stop
	chkconfig iptables off
}

function least_service(){
	#3.least service starup
	chkconfig|awk '{print "chkconfig",$1,"off"}'|bash
	chkconfig|egrep "crond|sshd|network|rsyslog|sysstat"|awk '{print "chkconfi",$1,"on"}'|bash
}

function adduser(){
	#4.add xiaoda and sudo
	if [ `grep -w xiaoda /etc/passwd|wc -l` -lt 1 ]
		then
			useradd xiaoda
			echo 123456|passwd --stdin xiaoda
			\cp /etc/sudoers /etc/sudoers.ori
			echo "xiaoda ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
			tail -l /etc/sudoers
			visudo -x &>/dev/null
	fi
}

function charset(){
	#5.charset config
	cp /etc/sysconfig/i18n /etc/sysconfig/i18n.ori
	echo 'LANG="zh_CN.UTF-8"' >/etc/sysconfig/i18n
	source /etc/sysconfig/i18n
}

function time_sync(){
	#6.time sync
	cron=/var/spool/cron/root
	if [ `grep -w "ntpdate" $cron|wc -l` -lt 1 ]
		then
			echo '#time sync by xiaoda at 2017-08-10' >> $cron
			echo '*/5 * * * * /usr/sbin/ntpdate time.nist.gov >dev/null 2>&1' >> $cron
			crontab -l
	fi
}

function com_line_set(){
	#7.command set
	if [ `egrep "TMOUT|HISTSIZE|ISTFILESIZE" /etc/profile |wc -l` -lt 3 ]
		then
			echo 'export TMOUT=300' >>/etc/profile
			echo 'export HISTSIZE=5' >>/etc/profile
			echo 'export ISTFILESIZE=5' >>/etc/profile
			. /etc/profile
	fi
}

function open_file_set(){
	#8.increase open file
	if [ `grep 65535 /etc/security/limits.conf|wc -l` -lt 1 ]
		then
			echo '* - nofile 65535' >> /etc/security/limits.conf
			tail -l /etc/security/limits.conf
	fi
}

function set_kernel(){
	#9.kernel set
	if [ `grep kernel_flag /etc/sysctl.conf|wc -l` -lt 1 ]
		then
			cat >>/etc/sysctl.conf<<EOF
			#kernel_flag
			net.ipv4.tcp_fin_timeout = 2
			net.ipv4.tcp_tw_reuse = 1
			net.ipv4.tcp_tw_recycle = 1
			net.ipv4.tcp_syncookies = 1
			net.ipv4.tcp_keepalive_time = 600
			net.ipv4.ip_local_port_range = 4000 65000
			net.ipv4.tcp_max_syn_backlog = 16384
			net.ipv4.tcp_max_tw_buckets = 36000
			net.ipv4.route.gc_timeout = 100
			net.ipv4.tcp_syn_retries = 1
			net.ipv4.tcp_synack_retries = 1
			net.core.somaxconn = 16384
			net.core.netdev_max_orphans = 16384
			net.ipv4.tcp_max_orphans = 16384
			net.nf_conntrack_max = 25000000
			net.netfilter.nf_conntrack_max = 25000000
			net.netfilter.nf_conntrack_tcp_timeout_established = 180
			net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
			net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
			net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120
EOF
			sysctl -p
	fi
}

function init_ssh(){
	\cp /etc/ssh/sshd_config /etc/ssh/sshd_config.`date +"%Y-%m-%d_%H-%M-%S"`
	sed -i 's%#Port 22%Port 52113%' /etc/ssh/sshd_config
	sed -i 's%#PermitRootLogin yes%PermitRootLogin no%' /etc/ssh/sshd_config
	sed -i 's%#PermitEmptyPasswords yes%PermitEmptyPasswords no%' /etc/ssh/sshd_config
	sed -i 's%#UseDNS yes%UseDNS no%' /etc/ssh/sshd_config
	/etc/init.d/sshd reload &>/dev/null
}

function update_linux(){
	#10.upgrade linux
	if [ `rpm -qa lrzsz nmap tree dos2unix nc|wc -l` -le 3]
		then
			yum install lrzsz nmap tree dos2unix nc -y
			yum update -y
	fi
}

main(){
	mod_yum
	close_selinux
	close_iptables
	least_service
	adduser
	charset
	time_sync
	com_line_set
	open_file_set
	set_kernel
	init_ssh
	ipdate_linux
}
main

检查脚本

[root@codis-178 ~]# cat check_opt.sh 
#!/bin/bash
# set env
export PATH=$PATH:/bin:/sbin:/usr/sbin

# Require root to run this script
if [ "$UID" != "0" ];then
	echo "Please run this script by root."
	exit 1
fi

# Source function library
. /etc/init.d/functions

function check_yum(){
	Base=/etc/yum.repos.d/centos6.7
	if [ `grep aliyun $Base|wc -l` -ge 1 ];then
		action "$Base config" /bin/true
	else
		action "$Base config" /bin/false
	fi
}

function check_selinux(){
	config=/etc/selinux/config
	if [ `grep "SELINUX=disabled" $config|wc -l` -ge 1 ];then
		action "$config config" /bin/true
	else
		action "$config config" /bin/false
	fi
}

function check_services(){
	export LANG=en
	if [ `chkconfig|grep 3:on|egrep "crond|sshd|network|rsyslog|sysstat"|wc -l` -eq 5 ];then
		action "sys service init" /bin/true
	else
		action "sys service init" /bin/false
	fi
}

function check_open_file(){
	limits=/etc/security/limits.conf
	if [ `grep 65535 $limits|wc -l` -eq 1 ];then
		action "$limits" /bin/true
	else
		action "$limits" /bin/false
	fi
}

main(){
	check_yum
	check_selinux
	check_service
	check_open_file
}
main

7.开发rsync启动脚本

[root@codis-178 ~]# cat rsync_start 
#!/bin/bash
# chkconfig: 2345 20 80
# description: Rsync Startup scripts
. /etc/init.d/functions

function usage(){
	echo $"usage:$0 {start|stop|restart}"
	exit 1
}

function start(){
	rsync --daemon
	sleep 1
	if [ `netstat -lntup |grep rsync|wc -l` -ge 1 ];then
		action "rsync is stared." /bin/true
	else
		action "rsync is stared." /bin/false
	fi
}

function stop(){
	killall rsync &>/dev/null
	sleep 2
	if [ `netstat -lntup|grep rsync|wc -l` -eq 0 ];then
		action "rsync is stopped." /bin/true
	else
		action "rsync is stopped." /bin/false
	fi
}

function main(){
	if [ $# -ne 1 ];then
		usage
	fi
	if [ "$1" = "start" ];then
		start
	elif [ "$1" = "stop" ];then
		stop
	elif [ "$1" = "restart" ];then
		stop
		sleep 1
		start
	else
		usage
	fi
}
main $*
posted @ 2017-08-30 18:01  BXBZ—边学边做  阅读(466)  评论(0编辑  收藏  举报