Linux_16 mktemp、trap命令任务计划(at/batch/cron)、小系统制作

1.变量中字符的长度: ${#VARNAME}
2.变量赋值等:
${parameter:-word}:如果parameter为空或未定义,则变量展开为"word";否则,展开为parameter的值;
${parameter:+word}:如果parameter为空或未定义,不做任何操作;否则,则展开为"word"值;
${parameter:=word}:如果parameter为空或未定义,则变量展开为"word",并将展开后的值赋值给parameter;
${parameter:offset}
${parameter:offset:length}:取子串,从offset处的后一个字符开始,取length长的子串;

cross compile:交叉编译
使用当前主机编译符合目标主机特征的编译方式,叫做交叉编译。
make ARCH=

mktemp 命令

创建临时文件或目录
mktemp /tmp/file.XX # 创建一个临时文件,XX的个数就是生成随机数的个数,不重复;
mktemp -d /tmp/file.XXXX  # 创建一个临时目录

image-20210521024939488

trap命令

EXIT:在shell退出前执行trap设置的命令,也可以指定为0
RETURN:在函数返回时,或者.和source执行其他脚本返回时,执行trap设置的命令
DEBUG:在任何命令执行前执行trap设置的命令,但对于函数仅在函数的第一条命令前执行一次

trap -l:列出所有信号的数值和名字,类似于kill -l
trap -p:列出通过trap设置的信号处理命令。

trap可以在收到信号前的任意位置设置,并非需要在脚本的第一行,但是shell是按照顺序执行语句的,不会优先执行trap

kill -SIGNAL PID
	 1:HUP
	 2:INT
	 9:KILL
	 15:TERM
脚本中,能实现信号捕捉,但9和15无法捕捉

Ctrl+c: SIGINT
trap命令:
	trap 'COMMAND' 信号列表
	

#!/bin/bash
#
NET=192.168.1

FILE=`mktemp /tmp/file.XXXX`
clearup() {
  echo "quit..."
  exit 1
}

trap 'clearup' INT  # trap 'clearup;exit 1' INT 一行执行多个语句,多个与巨剑用分号分隔。

for I in {0..20};do
  if ping -c 1 -W 3 $NET.$I &> /dev/null;then
    echo "$NET.$I is up." | tee >>$FILE
  else
    echo "$NET.$I is down."
  fi
done

任务计划

at和batch

1.再未来的某个时间点执行一次某任务
	安装at: yum install -y at
	systemctl start atd
	at 时间
	at> COMMAND
	at> Ctrl+d  # 提交任务
	指定时间:
		绝对时间:HH:MM, DD.MM.YY MM/DD/YY
		相对时间: now+#  # now+3minutes
		模糊时间:noon,midnight,teatime(1600)
	命令的执行结果:将以邮件的形式发送给安排任务的用户
	at -l =atq  # 查看当前任务列表
	at -d AT_JOB_ID = atrm AT_JOB_ID
	
	batch: 自动选择机器在较空间的时间执行任务,因此不需要指定时间。其他用法和at一样。
	
	可以对用户设定使用at任务计划的权限,具体参照 man at.allow 

cron

周期性地执行某任务
	cron:自身是一个不间断运行的服务
	anacron:cron的补充,能够实现让cron因为各种原因在过去的时间该执行而未执行的任务在恢复正常执行一次;
	cron:
		系统cron任务:和用户没有关系,是系统为了周期性地维护或运行某个任务而安排的,比如清理/tmp目录、locate命令的执行。
			/etc/crontab  # 一共有7个段,5个段指时间,1一个段指用户,1个段指要运行的任务。每个段用空格隔开
				分钟 小时 天 月 周 用户 任务
		用户cron任务:
			/var/spool/cron/USERNAME # 一共有6个段,5个段指时间,1个段指要运行的任务,不需要指用户
				分钟 小时 天 月 周 任务
		时间的有效取值范围:
			分钟:0-59
			小时:0-23
			天:1-31
			月:1-12
			周:0-7,0和7都表示周日
		时间通配表示:
			*:对应的所有有效取值
				3 * * * *  # 表示每个小时的第3分钟
				3 * * * 7  # 每个礼拜日每个小时的第3分钟
				13 12 * * 5  # 表示每周五的12点13分钟
				13 12 6 * *  # 表示每月的6号中午12点13分钟执行
				13 12 6 * 3 # 表示每月的6号 必须是周三的12点13分钟。 一般日和周单独使用
				13 12 6 7 * # 表示每年的7月6号中午的12点13分
			,:离散时间点:
				10,40 * * * * # 表示每小时的第10分钟和第40分钟各执行一次,即半小时任务
				10,40 * * 2,5 # 表示每周二和周五每小时的第10分钟和第40分钟各执行一次
				10,40 02 * 2,5 # 表示每周二和周五的凌晨两点的第10分钟和第40分钟各执行一次
			-:连续时间点:
				10 02 * * 1-5 # 表示每周的周一到周五的陵城两点的第10分钟各执行一次
			/#:对应取值范围内每多久一次
				*/3 * * * *  # 表示每3分钟一次的任务

			每两小时执行一次:
				08 */2 * * *
			每两天执行一次:
				10 04 */2 * *

与at一样,执行结果将以邮件形式发送给管理员;任务的执行结果有错误才发邮件。
	*/3 * * * * cat /etc/fstab > /dev/null 2>out.txt

cron的环境变量:cron执行所有命令都去PATH环境变量指定的路径下去找。
	PATH /bin:/sbin://usr/bin:/usr/sbin

在使用cron执行周期性任务的时候,可能用户没有登录,就不能以用户的身份运行周期性任务,此时就不能使用用户下的环境变量,所以在执行脚本时,可以使用命令的绝对路径去导出环境变量:
	#!/bin/bash
	#
	export PATH=


周期任务列表:
# 系统cron任务
vim /etc/crontab
    SHELL=/bin/bash
    PATH=/sbin:/bin:/usr/sbin:/usr/bin
    MAILTO=root
    HOME=/

    # run-parts 如果希望run-parts 对以下目录中中的任务有先后次序的执行,在创建文件时在文件名的前面加数字表示先后次序 比如: 0anacron 01logwatch
    01 * * * * root run-parts /etc/cron.hourly 
    02 4 * * * root run-parts /etc/cron.daily
    22 4 * * 0 root run-parts /etc/cron.weekly
    42 4 1 * * root run-parts /etc/cron.monthly

# 用户cron任务
	crontab:
		-l # 列出当前用户所有的计划任务
		-e # 编辑任务 专门编辑crontab任务,会在当前目录中生成一个当前登录用户名同名的文件,也可以vim 用户名,进去再编辑crontab任务,但是容易出错。建议 crontab -e
		-u USERNAME # 管理其他用户
			crontab -u hadoop -e # 以hadoop用户的身份编辑定时任务
			
            cd /var/spool/cron 
            crontab -e  # 
            */3 * * * * /bin/echo "how are you?"
            crontab -r # 删除/var/spool/cron 目录中的所有任务,文件将被删除。

anacron:
cat /etc/anacrontab
 
    [root@zhang ~]# cat /etc/anacrontab
    # /etc/anacrontab: configuration file for anacron

    # See anacron(8) and anacrontab(5) for details.

    SHELL=/bin/sh
    PATH=/sbin:/bin:/usr/sbin:/usr/bin
    MAILTO=root
    # the maximal random delay added to the base delay of the jobs
    RANDOM_DELAY=45
    # the jobs will be started during the following hours only
    START_HOURS_RANGE=3-22

    #period in days   delay in minutes   job-identifier          command
    1	                      5	           cron.daily	        nice run-parts /etc/cron.daily
    7	                      25	       cron.weekly          nice run-parts /etc/cron.weekly
    @monthly                  45	       cron.monthly		    nice run-parts /etc/cron.monthly
	
	1,7,@monthly:表示过去一天没有执行了,7代表七天没执行过了,@monthly表示过去一个月没有执行过了
	5,25,45:表示在开机以后第多少分钟执行
	
	anacron任务最小精确到天,而cron任务能精确到分钟。无论是cron还是anacron任务,都务必确保cron服务(crond  systemctl status crond)或anacron服务是运行的

小系统制作

which run-parts
	/usr/bin/run-parts
cat `which run-parts`

#!/bin/bash
# run-parts - concept taken from Debian

# keep going when something fails
set +e  # 表示在执行脚本的过程中如果出现异常时(return 1),自动退出。

if [ $# -lt 1 ]; then
	echo "Usage: run-parts [--list | --test] <dir>"
	exit 1
fi

while [ $# -gt 1 ]; do
	case $1 in
		--list)
			list=1
			shift
			break
			;;
		--test)
			test=1
			shift
			break
			;;
		--)
			# -- end of options
			shift
			break
			;;
		*)
			# directory
			break
			;;
	esac
done

if [ ! -d $1 ]; then
	echo "Not a directory: $1"
	exit 1
fi

if [ -f /etc/sysconfig/run-parts ]; then
	. /etc/sysconfig/run-parts
fi

# Ignore *~ and *, scripts
for i in $(LC_ALL=C; echo ${1%/}/*[^~,]) ; do
	[ -d $i ] && continue
	# Don't run *.{rpmsave,rpmorig,rpmnew,swp,cfsaved} scripts
	[ "${i%.cfsaved}" != "${i}" ] && continue
	[ "${i%.rpmsave}" != "${i}" ] && continue
        [ "${i%.rpmorig}" != "${i}" ] && continue
        [ "${i%.rpmnew}" != "${i}" ] && continue
        [ "${i%.swp}" != "${i}" ] && continue
	[ "${i%,v}" != "${i}" ] && continue

	# jobs.deny prevents specific files from being executed
	# jobs.allow prohibits all non-named jobs from being run.
	# can be used in conjunction but there's no reason to do so. 
	if [ -r $1/jobs.deny ]; then
		grep -q "^$(basename $i)$" $1/jobs.deny && continue
	fi
	if [ -r $1/jobs.allow ]; then
		grep -q "^$(basename $i)$" $1/jobs.allow || continue
	fi

	if [ -e $i ]; then
		if [ -r $1/whitelist ]; then
			grep -q "^$(basename $i)$" $1/whitelist && continue
		fi

		if [ ${list:-0} = 1 ]; then
			echo $i;
		elif [ -x $i ]; then
			if [ ${test:-0} = 1 ]; then
				echo $i;
				continue
			fi
			if [ "$RANDOMIZE" != "" ]; then
				let "rtime = $RANDOM"
				if [ "$RANDOMTIME" != "" ]; then
					let "rtime %= $RANDOMTIME"
				else
					let "rtime %= 300"
				fi
				sleep $rtime
			fi

			# run executable files
			logger -p cron.notice -t "run-parts($1)[$$]" "starting $(basename $i)"
			$i 2>&1 | awk -v "progname=$i" \
			      'progname {
				   print progname ":\n"
				   progname="";
			       }
			       { print; }'
			logger -i -p cron.notice -t "run-parts($1)" "finished $(basename $i)"
		fi
	fi
done

exit 0
Kernel + initrd(busybox制作,提供ext3文件系统模块) + ROOTFS(busybox制作)

make arch/
	arch/x86/boot/bzImage
	硬件驱动:initrd
		initrd:仅需要提供黑河访问真正的根文件系统所在设备需要的驱动
			存储设备和文件系统相关的模块
		系统初始化rc.sysinit:初始其它硬件驱动程序;
	ROOTFS:busybox,init不支持运行级别
		/etc/inittab:格式也不尽相同
vim init

#!/bin/sh
#
echo "mounting proc and sys..."
mount -t proc proc /proc
mount -t sysfs sysfs /sys

echo "Load ext3 module..."
insmod /lib/modules/jbd.ko
insmod /lib/modules/ext3.ko

echo "Detect and export hardware information"
mdev -s

echo "Mount real rootfs to /mnt/sysroot..."
mount -t ext3 /dev/hda2 /mnt/sysroot

echo "Switch to read rootfs..."
exec switch_root /mnt/sysroot /sbin/init

chmod +x init

modinfo jbd
	/lib/modules/2.6.18-308.el5/kernel/fs/jbd/jbd.ko
modinfo ext3
	/lib/modules/2.6.18-308.el5/kernel/fs/ext3/ext3.ko

cp /lib/modules/2.6.18-308.el5/kernel/fs/jbd/jbd.ko lib/modules  # 模块的版本一定要和内核版本一致,即使用内核编译之后的模块
cp /lib/modules/2.6.18-308.el5/kernel/fs/ext3/ext3.ko lib/modules

find . | cpio -H newc --quiet -o | gzip -9 > /mnt/boot/initrd.gz

vim /mnt/boot/grub/grub.conf

        default=0
        timeout=3
        title ChaoZhang Tiny Linux (2.6.18)
            root(hd0,0)
            kernel /vmlinuz ro root=/dev/hda2
            initrd /initrd.gz

cp -a busybox-1.20.2/_install/* /mnt/sysroot/ # /mnt/sysroot是制作的系统的真正的根
cd /mnt/sysroot
ls
	bin linuxrc sbin usr
rm linuxrc
mkdir boot root etc/rc.d/init.d var/{log,lock,run} proc sys dev lib/modules tmp home mnt media -pv
mknod dev/console c 5 1
mknod dev/null c 1 3 
vim etc/inittab
    ::sysinit:/etc/rc.d/rc.sysinit
    console::respawn:-/bin/sh
    ::ctrlaltdel:/sbin/reboot
    ::shutdown:/bin/umount -a -r

vim etc/rc.d/rc.sysinit
    #!/bin/bash
    #
    echo -e "\tWelcome to \033[34mChaoZhang Tiny\033[0m Linux"

    echo "Remount the rootfs..."
    mount -t ext3 -o remount,rw /dev/hda2 /

    echo "Mount the other filesystem..."
    mount -a

chmod +x etc/rc.d/rc.sysinit

vim /etc/fstab
    sysfs			/sys			sysfs	defaults		0  0
    proc			/proc			proc	defaults		0  0
    /dev/hda1		/boot             ext3	  defaults		  0  0
    /dev/hda2		/				ext3	defaults		1  1

sync

启动小系统
报错:
	mount:mounting /dev/hda1 on /boot failed:No such file or directory.
ls /dev
	console null
实际上 /boot目录我们在/mnt/sysroot已经创建,说明没有hda1,我们真正的根没有切换过来。小系统上的/dev没有切换过来,所以在 vim etc/rc.d/rc.sysinit 时,mdev -s 这一步不能少。

vim etc/rc.d/rc.sysinit
    #!/bin/bash
    #
    echo -e "\tWelcome to \033[34mChaoZhang Tiny\033[0m Linux"

    echo "Remount the rootfs..."
    mount -t ext3 -o remount,rw /dev/hda2 /
	
	echo -e "Creating the files of device..."
	mdev -s
	
    echo "Mount the other filesystem..."
    mount -a

启动小系统
报错:
	mount:mounting /dev/hda1 on /boot failed:No such file or directory.
说明busybox提供的switch-root命令和红帽提供的根切换的命令不一样,这个命令没办法将小系统的proc、dev和sys目录都搬过来,但是红帽的可以。所以还需要重新挂载proc、dev、sys

vim etc/rc.d/rc.sysinit
    #!/bin/bash
    #
    echo -e "\tWelcome to \033[34mChaoZhang Tiny\033[0m Linux"
	
	echo "mount proc and sys..."
	mount -t proc proc /proc
	mount -t sysfs sysfs /sys
	
    echo "Remount the rootfs..."
    mount -t ext3 -o remount,rw /dev/hda2 /

    echo "Mount the other filesystem..."
    mount -a
   
sync

重启小系统
正常
ls /dev  # 都是mdev自动创建的
ls /proc
ls /sys

更换sh到bash
./bincp.sh
	bash
chroot /mnt/sysroot

cd bin/
	查看到
		sh-->busybox  
		我们需要将bash-->busybox , 但是一般不要更改busybox默认的sh,我们可以修改 etc/inittab:
			console::respawn:-/bin/sh --> console::respawn:-/bin/bash

给小系统提供账号密码:
	grep -E "^root:" /etc/passwd >/mnt/sysroot/etc/passwd
	grep -E "^root:" /etc/shadow >/mnt/sysroot/etc/shadow
	grep -E "^root:" /etc/group >/mnt/sysroot/etc/group
ls /mnt/sysroot/etc/
chmod 400 /mnt/sysroot/etc/shadow 
查看/mnt/sysroot/etc/passwd文件中root用户使用的shell:
	root:x:0:0:root:/root:/bin/bash  
如果小系统没有移植bash,那这里就需要改成/bin/sh,不然用户登录不了

sync

vim /etc/inittab # 删除console行 并编辑两个虚拟终端 tty
	::sysinit:/etc/rc.d/rc.sysinit
    ::respawn:/sbin/getty 9600 tty1
    ::respawn:/sbin/getty 9600 tty2
    ::ctrlaltdel:/sbin/reboot
    ::shutdown:/bin/umount -a -r

sync

希望登录的时候有主机名:
	vim /mnt/sysroot/etc/hostname
		HOSTNAME=tiny.ChaoZhang.com
	vim /mnt/sysroot/etc/inittab

        echo "Set the hostname..."
        [ -f /etc/hostname ] && . /etc/hostname
        [ -z "$HOSTNAME" -o "$HOSTNAME" == '(none)' ] && HOSTNAME=localhost
        hostname=$HOSTNAME
	vim /mnt/sysroot/etc/issue # 启动系统终端最先显示的信息
		cp /etc/issue /mnt/sysroot/etc
sync

find . | cpio -H newc --quiet -o | gzip > /root/tiny.1.gz
du -sh /root/tiny.1.gz  # 压缩后就几兆的大小

报错:
	EXT3-fs error (device hda2):ext3_lookup:unlinked inode 76917 in dir #76917 ext3_abort called.
	EXT3-fs error (device hda2):ext3_journal_start_sb:Detected aborted journal Remounting filesystem read-only
umount /mnt/sysroot
mke2fss -j /dev/hda2
mount /dev/hda2 /mnt/sysroot
cd /mnt/sysroot
zcat /root/tiny.1.gz cpio -id
sync

# 能够装载网卡,提供网卡驱动,提供IP
cd /mnt/sysroot
modinfo mii
	/lib/modules/2.6.18-308.el5/kernel/drivers/net/mii.ko
modinfo pcnet32
	/lib/modules/2.6.18-308.el5/kernel/drivers/net/pcnet32.ko
cp /lib/modules/2.6.18-308.el5/kernel/drivers/net/mii.ko
modinfo pcnet32 lib/modules
cp /lib/modules/2.6.18-308.el5/kernel/drivers/net/pcnet32.ko lib/modules

vim etc/inittab

    # 在所有设备都探测好以后,再装载驱动
    echo "Load ethernet card module..."
    insmod /lib/modules/mii.ko
    insmod /lib/modules/pcnet32.ko
    ifconfig ens1 172.16.100.13/16
    ifconfig lo 127.0.0.1/8

posted on 2021-05-22 11:55  jueyuanfengsheng  阅读(153)  评论(0编辑  收藏  举报