├── 01_parted_mkfs ├── 1_parted.sh ├── 2_mkfs.sh ├── 3_mkdir.sh └── 4_mount.sh ├── 02_raid_monitor └── raid_monitor.sh ├── 03_keepalived_check ├── README.md └── keepalived_check.py ├── 04_linux_iptables └── linux_drop_port.sh ├── 05_change_hostname └── change_hostname_centos.sh ├── 06_denyhosts ├── README.md └── denyhosts.sh ├── 07_audit_action ├── README.md └── audit_action.sh ├── 08_rm ├── README.md └── rmtrash.sh ├── 09_screen ├── README.md └── screen.sh ├── 10_rebuild_centos └── rebuild_centos6.x_X64_image.sh ├── 11_shell_common ├── README.md ├── scan_disk │ └── scan_disk.sh ├── shell_processbar │ ├── ProcessBash1.sh │ └── ProcessBash2.sh ├── shell_whiptail │ ├── checklist.sh │ ├── input-box.sh │ ├── menu-box.sh │ ├── password-box.sh │ ├── progress-bar.sh │ ├── radiolist.sh │ ├── yes-no.sh │ └── yes-no2.sh └── trap_err │ ├── README.md │ └── trap_err.sh ├── 12_blogger ├── README.md ├── b_lib │ └── log.sh └── test.sh ├── 13_mount_file ├── README.md └── mount_file.sh ├── 14_daemon ├── README.md └── run.sh ├── 15_tcpcopy ├── README.md ├── run.sh └── tcp_copy │ ├── cept.sh │ └── copy.sh ├── 16_truncate └── README.md ├── 17_logrotate ├── README.md ├── log_control.sh ├── log_rotate_lib │ ├── log.sh │ └── op_log_rotate.sh ├── logrotate_exe.sh └── logrotate_loop.sh ├── 18_opmv └── opmv ├── LICENSE └── README.md /01_parted_mkfs/1_parted.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | PATH=/bin:/sbin:/usr/bin:/usr/sbin 3 | i=1 4 | while [ $i -lt 13 ] 5 | do 6 | j=`echo $i|awk '{printf "%c",97+$i}'` 7 | echo $j 8 | parted /dev/sd$j << End 9 | mklabel gpt 10 | mkpart primary 0% 100% 11 | quit 12 | End 13 | let i+=1 14 | done 15 | -------------------------------------------------------------------------------- /01_parted_mkfs/2_mkfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | PATH=/bin:/sbin:/usr/bin:/usr/sbin 3 | i=1 4 | while [ $i -lt 13 ] 5 | do 6 | j=`echo $i|awk '{printf "%c",97+$i}'` 7 | echo $j 8 | mkfs.ext4 /dev/sd${j}1 & 9 | let i+=1 10 | done 11 | -------------------------------------------------------------------------------- /01_parted_mkfs/3_mkdir.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | PATH=/bin:/sbin:/usr/bin:/usr/sbin 3 | i=1 4 | while [ $i -lt 13 ] 5 | do 6 | j=`echo $i|awk '{printf "%c",97+$i}'` 7 | echo $j 8 | mkdir -p /mnt/sd$j 9 | let i+=1 10 | done 11 | -------------------------------------------------------------------------------- /01_parted_mkfs/4_mount.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | PATH=/bin:/sbin:/usr/bin:/usr/sbin 3 | i=1 4 | while [ $i -lt 13 ] 5 | do 6 | j=`echo $i|awk '{printf "%c",97+$i}'` 7 | echo $j 8 | mount /dev/sd${j}1 /mnt/sd$j 9 | let i+=1 10 | done 11 | -------------------------------------------------------------------------------- /02_raid_monitor/raid_monitor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #check raid disk status 3 | 4 | MEGACLI="sudo /opt/MegaRAID/MegaCli/MegaCli64 " 5 | 6 | $MEGACLI -pdlist -aALL -NoLog | grep "Firmware state" | awk -F : '{print $2}' | awk -F , '{print $1}' >/tmp/fireware.log 7 | $MEGACLI -pdlist -aALL -NoLog | grep -E "Media Error|Other Error" | awk -F : '{print $2}' >/tmp/disk.log 8 | 9 | for i in `cat < /tmp/disk.log` 10 | do 11 | if [ $i -ne 0 ];then 12 | echo "raid_disk_error" 13 | fi 14 | done 15 | 16 | for i in `cat < /tmp/fireware.log` 17 | do 18 | if [ $i != Online ];then 19 | echo "raid_disk_offline" 20 | fi 21 | done 22 | -------------------------------------------------------------------------------- /03_keepalived_check/README.md: -------------------------------------------------------------------------------- 1 | # keepalived-tools 2 | ## keepalived_checker.py 3 | ### Description 4 | Check duplications or typo of VRRP IDs (vrid), Virtual IP Addresses (vrip) and Virtual Servers (vs) from 'keepalived.conf'. 5 | 6 | ### Tested on 7 | - CentOS 6.5 8 | - keepalived-1.2.13 9 | 10 | ### Required 11 | - Python 2.6 or 2.7 12 | 13 | ### Usage 14 | Simply, run it. 15 | 16 | ``` 17 | $ ./keepalived_checker.py 18 | ``` 19 | 20 | If your config file is located on non default path, add `-f`. 21 | 22 | ``` 23 | $ ./keepalived_checker.py -f CONF_PATH 24 | ``` 25 | 26 | ### Output Examples 27 | You will get output like this if NG has found. 28 | 29 | ``` 30 | $ ./keepalived_checker.py 31 | 'virtual_server' duplications found: 32 | 192.168.1.1:80 33 | - /etc/keepalived/keepalived.conf:20 34 | - /etc/keepalived/conf.d/test.conf:2 35 | ``` 36 | 37 | If no errors found, get this. 38 | 39 | ``` 40 | $ ./keepalived_checker.py 41 | OK 42 | ``` 43 | -------------------------------------------------------------------------------- /03_keepalived_check/keepalived_check.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | #coding=utf8 3 | """ 4 | # Author: Bill 5 | # Created Time : 2016年05月28日 星期六 12时22分00秒 6 | 7 | # File Name: keepalived_check.py 8 | # Description: 9 | 10 | """ 11 | import os, sys, re 12 | import glob 13 | import optparse 14 | version = "0.1.0" 15 | 16 | def_conf_path = '/etc/keepalived/keepalived.conf' 17 | 18 | regex_confline = re.compile(r'''^(?P[^!#]+)(.*)$''', flags=re.IGNORECASE) 19 | regex_include = re.compile(r'''^\s*include\s+(?P[^\s]+).*$''', flags=re.IGNORECASE) 20 | # config regex 21 | regex_vrid = re.compile(r'''^\s*virtual_router_id\s+(?P\d+).*$''', flags=re.IGNORECASE) 22 | regex_vip = re.compile(r'''^\s*(?P(\d{1,3}\.){3}\d{1,3}).*$''', flags=re.IGNORECASE) 23 | regex_vs = re.compile(r'''^\s*virtual_server\s+(?P(\d{1,3}\.){3}\d{1,3})\s+(?P\d+).*$''', flags=re.IGNORECASE) 24 | 25 | 26 | def read_config(path=""): 27 | ''' 28 | read_config read configs with support include stetement, 29 | and remove comments or blank lines. 30 | returns: 31 | list of tupple(parameter, filename:index) 32 | ''' 33 | conf_dir = os.path.dirname(path) 34 | 35 | try: 36 | config = list() 37 | num = 0 38 | for line in open(path): 39 | num += 1 40 | m = regex_confline.match(line) 41 | if m is None : 42 | continue 43 | ### parse 44 | param = m.group('param').rstrip() 45 | m_include = regex_include.match(param) 46 | if m_include : 47 | include_path = m_include.group('path') 48 | for p in glob.glob('/'.join([conf_dir, include_path])): 49 | config.extend(read_config(p)) 50 | else : 51 | index = "%s:%i" % (path, num) 52 | config.append((param, index)) 53 | 54 | return config 55 | except: 56 | raise IOError("conffile '%s' not found" % path) 57 | 58 | def parse_config(config=[]): 59 | vrids = list() 60 | vips = list() 61 | virtual_servers = list() 62 | 63 | for line, index in config: 64 | # vrid 65 | m = regex_vrid.match(line) 66 | if m : 67 | vrids.append((m.group('vrid'), index)) 68 | continue 69 | # virtual_server 70 | m = regex_vs.match(line) 71 | if m : 72 | virtual_servers.append(((m.group('vip'),m.group('port')), index)) 73 | continue 74 | # vip 75 | m = regex_vip.match(line) 76 | if m : 77 | vips.append((m.group('vip'), index)) 78 | continue 79 | 80 | return vrids, vips, virtual_servers 81 | 82 | 83 | def check_vrids(vrids): 84 | dups = __check_vrids_dup(vrids) 85 | return len(dups) == 0 86 | 87 | def __check_vrids_dup(vrids): 88 | vrid_list = list( map(lambda x: x[0], vrids) ) 89 | unique_list = list(set( map(lambda x: x[0], vrids) )) 90 | 91 | for ele in unique_list: 92 | vrid_list.remove(ele) 93 | 94 | if len(vrid_list) > 0 : 95 | print("'virtual_router_id' duplications found:") 96 | for ele in vrid_list: 97 | print("\t" + ele) 98 | for vrid, index in vrids: 99 | if vrid == ele : 100 | print("\t\t- %s" % index) 101 | print 102 | return vrid_list 103 | 104 | 105 | 106 | def check_vips(vips, virtual_servers): 107 | dups_vip = __check_vips_dup(vips) 108 | dups_vs = __check_vs_dup(virtual_servers) 109 | ng_vips = __check_vips_unmanaged(vips, virtual_servers) 110 | if (len(dups_vip) + len(dups_vs) + len(ng_vips)) == 0 : 111 | return True 112 | else: 113 | return False 114 | 115 | def __check_vips_dup(vips): 116 | vip_list = map(lambda x: x[0], vips) 117 | unique_list = list(set(vip_list)) 118 | 119 | for ele in unique_list: 120 | vip_list.remove(ele) 121 | 122 | if len(vip_list) > 0 : 123 | print("'virtual_ipaddress' duplications found:") 124 | for ele in vip_list: 125 | print("\t" + ele) 126 | for vip, index in vips: 127 | if vip == ele : 128 | print("\t\t- %s" % index) 129 | print 130 | 131 | return vip_list 132 | 133 | def __check_vs_dup(virtual_servers): 134 | vs_list = map(lambda x: x[0], virtual_servers) 135 | unique_list = list(set(vs_list)) 136 | 137 | for ele in unique_list: 138 | vs_list.remove(ele) 139 | 140 | if len(vs_list) > 0 : 141 | print("'virtual_server' duplications found:") 142 | for ele in vs_list: 143 | print("\t" + ':'.join(ele)) 144 | for vs, index in virtual_servers: 145 | if vs == ele : 146 | print("\t\t- %s" % index) 147 | print 148 | 149 | return vs_list 150 | 151 | 152 | def __check_vips_unmanaged(vips, virtual_servers): 153 | managed_list = map(lambda x: x[0], vips) 154 | unmanaged_list = list() 155 | 156 | for (vip, port) in map(lambda x: x[0], virtual_servers): 157 | if vip not in managed_list : 158 | unmanaged_list.append((vip, port)) 159 | 160 | if len(unmanaged_list) > 0 : 161 | print("'virtual_server' uses unmanaged VIP:") 162 | for ele in unmanaged_list: 163 | print("\t" + ':'.join(ele)) 164 | for vs, index in virtual_servers: 165 | if vs == ele : 166 | print("\t\t- %s" % index) 167 | print 168 | 169 | return unmanaged_list 170 | 171 | 172 | 173 | if __name__ == "__main__": 174 | import optparse 175 | usage = """usage: %prog [options]""" 176 | 177 | parser = optparse.OptionParser(usage=usage, version=version) 178 | parser.add_option( 179 | "-f", "--file", 180 | action="store", 181 | dest="conf_path", 182 | default=def_conf_path, 183 | help="set keepalived config file path. (default:%s)" % def_conf_path 184 | ) 185 | (options, args) = parser.parse_args() 186 | if len(args) != 0 : 187 | parser.print_help() 188 | sys.exit(3) 189 | 190 | config = read_config(options.conf_path) 191 | vrids, vips, virtual_servers = parse_config(config) 192 | 193 | ret = 0 194 | if check_vrids(vrids) != True : 195 | ret = 1 196 | if check_vips(vips, virtual_servers) != True : 197 | ret = 1 198 | 199 | if ret == 0 : 200 | print("OK") 201 | sys.exit(ret) 202 | -------------------------------------------------------------------------------- /04_linux_iptables/linux_drop_port.sh: -------------------------------------------------------------------------------- 1 | ######################################################################### 2 | # File Name: linux_drop_port.sh 3 | # Author: Bill 4 | # mail: XXXXXXX@qq.com 5 | # Created Time: 2016-06-02 22:57:25 6 | ######################################################################### 7 | #!/bin/bash 8 | 9 | #check_os_release{{{1 10 | check_os_release() 11 | { 12 | while true 13 | do 14 | os_release=$(grep "Red Hat Enterprise Linux Server release" /etc/issue 2>/dev/null) 15 | os_release_2=$(grep "Red Hat Enterprise Linux Server release" /etc/redhat-release 2>/dev/null) 16 | if [ "$os_release" ] && [ "$os_release_2" ] 17 | then 18 | if echo "$os_release"|grep "release 5" >/dev/null 2>&1 19 | then 20 | os_release=redhat5 21 | echo "$os_release" 22 | elif echo "$os_release"|grep "release 6" >/dev/null 2>&1 23 | then 24 | os_release=redhat6 25 | echo "$os_release" 26 | else 27 | os_release="" 28 | echo "$os_release" 29 | fi 30 | break 31 | fi 32 | os_release=$(grep "Aliyun Linux release" /etc/issue 2>/dev/null) 33 | os_release_2=$(grep "Aliyun Linux release" /etc/aliyun-release 2>/dev/null) 34 | if [ "$os_release" ] && [ "$os_release_2" ] 35 | then 36 | if echo "$os_release"|grep "release 5" >/dev/null 2>&1 37 | then 38 | os_release=aliyun5 39 | echo "$os_release" 40 | elif echo "$os_release"|grep "release 6" >/dev/null 2>&1 41 | then 42 | os_release=aliyun6 43 | echo "$os_release" 44 | else 45 | os_release="" 46 | echo "$os_release" 47 | fi 48 | break 49 | fi 50 | os_release=$(grep "CentOS release" /etc/issue 2>/dev/null) 51 | os_release_2=$(grep "CentOS release" /etc/*release 2>/dev/null) 52 | if [ "$os_release" ] && [ "$os_release_2" ] 53 | then 54 | if echo "$os_release"|grep "release 5" >/dev/null 2>&1 55 | then 56 | os_release=centos5 57 | echo "$os_release" 58 | elif echo "$os_release"|grep "release 6" >/dev/null 2>&1 59 | then 60 | os_release=centos6 61 | echo "$os_release" 62 | else 63 | os_release="" 64 | echo "$os_release" 65 | fi 66 | break 67 | fi 68 | os_release=$(grep -i "ubuntu" /etc/issue 2>/dev/null) 69 | os_release_2=$(grep -i "ubuntu" /etc/lsb-release 2>/dev/null) 70 | if [ "$os_release" ] && [ "$os_release_2" ] 71 | then 72 | if echo "$os_release"|grep "Ubuntu 10" >/dev/null 2>&1 73 | then 74 | os_release=ubuntu10 75 | echo "$os_release" 76 | elif echo "$os_release"|grep "Ubuntu 12.04" >/dev/null 2>&1 77 | then 78 | os_release=ubuntu1204 79 | echo "$os_release" 80 | elif echo "$os_release"|grep "Ubuntu 12.10" >/dev/null 2>&1 81 | then 82 | os_release=ubuntu1210 83 | echo "$os_release" 84 | else 85 | os_release="" 86 | echo "$os_release" 87 | fi 88 | break 89 | fi 90 | os_release=$(grep -i "debian" /etc/issue 2>/dev/null) 91 | os_release_2=$(grep -i "debian" /proc/version 2>/dev/null) 92 | if [ "$os_release" ] && [ "$os_release_2" ] 93 | then 94 | if echo "$os_release"|grep "Linux 6" >/dev/null 2>&1 95 | then 96 | os_release=debian6 97 | echo "$os_release" 98 | else 99 | os_release="" 100 | echo "$os_release" 101 | fi 102 | break 103 | fi 104 | os_release=$(grep "openSUSE" /etc/issue 2>/dev/null) 105 | os_release_2=$(grep "openSUSE" /etc/*release 2>/dev/null) 106 | if [ "$os_release" ] && [ "$os_release_2" ] 107 | then 108 | if echo "$os_release"|grep "13.1" >/dev/null 2>&1 109 | then 110 | os_release=opensuse131 111 | echo "$os_release" 112 | else 113 | os_release="" 114 | echo "$os_release" 115 | fi 116 | break 117 | fi 118 | break 119 | done 120 | } 121 | #exit_script{{{1 122 | exit_script() 123 | { 124 | echo -e "\033[1;40;31mInstall $1 error,will exit.\n\033[0m" 125 | rm -f $LOCKfile 126 | exit 1 127 | } 128 | 129 | #config_iptables{{{1 130 | config_iptables() 131 | { 132 | iptables -I OUTPUT 1 -p tcp -m multiport --dport 21,22,23,25,53,80,135,139,443,445 -j DROP 133 | iptables -I OUTPUT 2 -p tcp -m multiport --dport 1433,1314,1521,2222,3306,3433,3389,4899,8080,18186 -j DROP 134 | iptables -I OUTPUT 3 -p udp -j DROP 135 | iptables -nvL 136 | } 137 | #ubuntu_config_ufw{{{1 138 | ubuntu_config_ufw() 139 | { 140 | ufw deny out proto tcp to any port 21,22,23,25,53,80,135,139,443,445 141 | ufw deny out proto tcp to any port 1433,1314,1521,2222,3306,3433,3389,4899,8080,18186 142 | ufw deny out proto udp to any 143 | ufw status 144 | } 145 | 146 | #}}} 147 | ####################Start################### 148 | #check lock file ,one time only let the script run one time 149 | LOCKfile=/tmp/.$(basename $0) 150 | if [ -f "$LOCKfile" ] 151 | then 152 | echo -e "\033[1;40;31mThe script is already exist,please next time to run this script.\n\033[0m" 153 | exit 154 | else 155 | echo -e "\033[40;32mStep 1.No lock file,begin to create lock file and continue.\n\033[40;37m" 156 | touch $LOCKfile 157 | fi 158 | 159 | #check user 160 | if [ $(id -u) != "0" ] 161 | then 162 | echo -e "\033[1;40;31mError: You must be root to run this script, please use root to execute this script.\n\033[0m" 163 | rm -f $LOCKfile 164 | exit 1 165 | fi 166 | 167 | echo -e "\033[40;32mStep 2.Begen to check the OS issue.\n\033[40;37m" 168 | os_release=$(check_os_release) 169 | if [ "X$os_release" == "X" ] 170 | then 171 | echo -e "\033[1;40;31mThe OS does not identify,So this script is not executede.\n\033[0m" 172 | rm -f $LOCKfile 173 | exit 0 174 | else 175 | echo -e "\033[40;32mThis OS is $os_release.\n\033[40;37m" 176 | fi 177 | 178 | echo -e "\033[40;32mStep 3.Begen to config firewall.\n\033[40;37m" 179 | case "$os_release" in 180 | redhat5|centos5|redhat6|centos6|aliyun5|aliyun6) 181 | service iptables start 182 | config_iptables 183 | ;; 184 | debian6) 185 | config_iptables 186 | ;; 187 | ubuntu10|ubuntu1204|ubuntu1210) 188 | ufw enable < 5 | * [ssh暴力破解检测方法](#ssh暴力破解检测方法) 6 | * [ssh防暴力破解方法](#ssh防暴力破解方法) 7 | * [提升ssh安全](#提升ssh安全) 8 | * [修改sshd服务器的配置文件/etc/ssh/sshd_config](#修改sshd服务器的配置文件/etc/ssh/sshd_config) 9 | * [修改sshd服务器的配置文件/etc/ssh/sshd_config的读写权限,](#修改sshd服务器的配置文件/etc/ssh/sshd_config的读写权限,) 10 | * [设置TCP Wrappers](#设置tcp-wrappers) 11 | * [尽量关闭一些系统不需要的启动服务](#尽量关闭一些系统不需要的启动服务) 12 | * [其他](#其他) 13 | 14 | 15 | 16 | ### ssh暴力破解检测方法 17 | 18 | 输出尝试密码失败IP列表 19 | ``` 20 | # cat /var/log/secure | awk '/Failed/{print $(NF-3)}' | sort | uniq -c | awk '{print $2" = "$1;}'| sort -n -k 2 -t = -r 21 | ``` 22 | 23 | ### ssh防暴力破解方法 24 | 25 | (1)简单脚本操作 26 | 27 | 原理就是定时检查/var/log/secure中尝试密码登陆IP,超过10次后,将此IP放到/etc/hosts.deny中,禁止ssh登陆 28 | 29 | 通过crontab来执行,每天的1点0分执行一次。 30 | 31 | 0 1 * * * sh /root/bin/denyhosts.sh 32 | 33 | 下载方式 34 | ``` 35 | #curl -o denyhosts.sh https://raw.githubusercontent.com/BillWang139967/linux_tools/master/06_denyhosts/denyhosts.sh 36 | ``` 37 | 38 | (2)DenyHosts 39 | 40 | 据说有点坑,就不详细介绍了 41 | 42 | ## 提升ssh安全 43 | 44 | ### 修改sshd服务器的配置文件/etc/ssh/sshd_config 45 | 46 | * Port 5555 #系统缺省使用22号端口 47 | * ListenAddress 192.168.0.1 #设定sshd只在其中一个指定的接口地址监听,这样可以减少sshd的入口,降低入侵的可能性。 48 | * PermitRootLogin no #禁止root用户登录 49 | * PermitEmptyPasswords no #禁止空密码登陆 50 | * Protocol 2 #禁止使用版本1协议,因为其存在设计缺陷,很容易使密码被黑掉。 51 | 52 | ### 修改sshd服务器的配置文件/etc/ssh/sshd_config的读写权限, 53 | 54 | 对所有非root用户设置只读权限,防止非授权用户修改sshd服务的安全设置。 55 | ``` 56 | chmod 644 /etc/ssh/sshd_config 57 | ``` 58 | ### 设置TCP Wrappers 59 | 60 | 使用TCPWrappers可以阻止或允许应用服务仅对某些主机开放,给系统在增加一道安全屏障。 61 | 62 | 这部分设置共涉计到两个文件:hosts.allow和hosts.deny。 63 | 64 | 如系统仅允许IP地址为192.168.0.15和10.0.0.11的主机使用sshd服务, 65 | ``` 66 | 在/etc/hosts.allow中添加 67 | sshd:192.168.0.15 10.0.0.11 68 | 69 | 在/etc/hosts.deny中添加 70 | sshd:All 71 | ``` 72 | 注意:系统对上述两个文件的判断顺序是先检查hosts.allow文件再查看hosts.deny文件 73 | 74 | ### 尽量关闭一些系统不需要的启动服务 75 | 76 | ## 其他 77 | 78 | 检测近期用户登录登陆情况 79 | 80 | [shell_menu](https://github.com/BillWang139967/shell_menu/wiki) 81 | -------------------------------------------------------------------------------- /06_denyhosts/denyhosts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #Denyhosts SHELL SCRIPT 3 | 4 | cat /var/log/secure|awk '/Failed/{print $(NF-3)}'|sort|uniq -c|awk '{print $2"=" $1;}' >/tmp/Denyhosts.txt 5 | DEFINE="10" 6 | for i in `cat /tmp/Denyhosts.txt` 7 | do 8 | IP=`echo $i|awk -F= '{print $1}'` 9 | NUM=`echo $i|awk -F= '{print $2}'` 10 | if [ $NUM -gt $DEFINE ] 11 | then 12 | grep $IP /etc/hosts.deny >/dev/null 13 | if [ $? -gt 0 ]; 14 | then 15 | echo "sshd:$IP" >> /etc/hosts.deny 16 | fi 17 | fi 18 | done 19 | -------------------------------------------------------------------------------- /07_audit_action/README.md: -------------------------------------------------------------------------------- 1 | ## 使用[PROMPT_COMMAND]变量 实现审计操作行为功能 2 | 3 | ### 安装 4 | ``` 5 | #curl -o audit_action.sh https://raw.githubusercontent.com/BillWang139967/linux_tools/master/07_audit_action/audit_action.sh 6 | #bash audit_action.sh 7 | ``` 8 | ### 提示 9 | 10 | 此日志文件如果需要删除时,在执行删除操作时,会提示没有权限,这个就是chattr对文件实现的保护功能了,如果需要删除此文件,需要执行 11 | 12 | ``` 13 | chattr -a /var/log/Command_history.log 14 | chmod 777 /var/log/Command_history.log 15 | ``` 16 | 17 | 然后对日志文件进行删除操作 18 | 19 | ### 相关 20 | 21 | [ssh_menu](https://github.com/BillWang139967/shell_menu) 22 | -------------------------------------------------------------------------------- /07_audit_action/audit_action.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | FILENAME="/var/log/Command_history.log" 4 | PATHNAME="/etc/profile" 5 | FINDNAME="HISTORY_FILE" 6 | if [[ ! -f ${FILENAME} ]] 7 | then 8 | #创建行为审计日志文件 9 | touch ${FILENAME} 10 | #将日志文件的所有者改为权限低的用户NOBODY 11 | chown nobody:nobody ${FILENAME} 12 | #赋予所有用户对日志文件写的权限 13 | chmod 002 ${FILENAME} 14 | #使所有用户对日志文件只有追加权限 15 | chattr +a ${FILENAME} 16 | fi 17 | 18 | if [[ `cat ${PATHNAME} | grep ${FINDNAME} | wc -l` < 1 ]]; then 19 | cat >> ${PATHNAME} <<"EOF" 20 | export HISTORY_FILE=/var/log/Command_history.log 21 | export PROMPT_COMMAND='{ date "+%y-%m-%d %T ##### $(who am i |awk "{print \$1\" \"\$2\" \"\$5}") #### $(history 1 | { read x cmd; echo "$cmd"; })"; } >>${HISTORY_FILE}' 22 | EOF 23 | else 24 | exit 0 25 | fi 26 | -------------------------------------------------------------------------------- /08_rm/README.md: -------------------------------------------------------------------------------- 1 | 开启linux和mac下命令行版本rm的回收站 2 | 3 | * [适用系统](#适用系统) 4 | * [使用说明](#使用说明) 5 | * [安装](#安装) 6 | * [使用](#使用) 7 | * [功能说明](#功能说明) 8 | * [彻底删除文件](#彻底删除文件) 9 | 10 | ## 适用系统 11 | 12 | > * Linux 13 | > * mac 14 | 15 | ## 使用说明 16 | 17 | ### 安装 18 | 19 | ``` 20 | #curl -o rmtrash.sh https://raw.githubusercontent.com/BillWang139967/linux_tools/master/08_rm/rmtrash.sh 21 | #mv rmtrash.sh /bin/ 22 | #chmod +x /bin/rmtrash.sh 23 | #/bin/rmtrash.sh 24 | #source ~/.bashrc 25 | ``` 26 | 27 | 如果想对全局所有用户启用回收站,需要修改bashrc全局配置文件后即可: 28 | echo "alias rm=/bin/rmtrash.sh" >>/etc/bashrc 29 | 30 | ### 使用 31 | rm -h 32 | Usage: rm file1 [file2] [dir3] [....] delete the files or dirs,and mv them to the rmtrash recycle bin 33 | rm is alias to rmtrash.sh. 34 | options: 35 | -f mv one or more files to the rmtrash recycle bin 36 | -r mv one or more files to the rmtrash recycle bin 37 | -fr mv one or more files to the rmtrash recycle bin 38 | -rf mv one or more files to the rmtrash recycle bin 39 | -R Restore selected files to the originalpath from rmtrash recycle bin 40 | -l list the contens of rmtrash recycle bin 41 | -i show detailed log of the deleted file history 42 | -d delete one or more files by user's input file name from the trash 43 | -e empty the rmtrash recycle bin 44 | -h display this help menu 45 | 46 | ## 功能说明 47 | 48 | ### 彻底删除文件 49 | ``` 50 | # rm -e 清空回收站 51 | # /bin/rm file 直接删除文件而不经过回收站 52 | ``` 53 | -------------------------------------------------------------------------------- /08_rm/rmtrash.sh: -------------------------------------------------------------------------------- 1 | ######################################################################### 2 | # File Name: w.sh 3 | # Author: meetbill 4 | # mail: meetbill@163.com 5 | # Created Time: 2016-12-01 23:46:50 6 | ######################################################################### 7 | #!/bin/bash 8 | ### rmtrash,rm command line recycle bin for linux and mac osx. 9 | ### rmtrash 是linux和mac下命令行版本rm的回收站,安装后对用户透明,符合正常使用rm的习惯(支持rm -fr file哦),有了他再也不怕rm时候手颤抖了。 10 | 11 | ##################################################################################### 12 | # 更新说明: 13 | # 1.0.2 : 修复rm -e 清空回收站时无法清空.开头的隐藏文件 14 | # 15 | # 16 | ##################################################################################### 17 | 18 | ###trash目录define 19 | realrm="/bin/rm" 20 | trash_dir=~/.rmtrash/ 21 | trash_log=~/.rmtrash.log 22 | ###判断trash目录是否存在,不存在则创建 23 | if [ ! -d $trash_dir ] ;then 24 | mkdir -v $trash_dir 25 | fi 26 | 27 | ###动态修改用户shell中的alias配置 28 | os_type=`uname` 29 | shell_path=$SHELL 30 | shell_type=`echo $SHELL|awk -F/ '{print $NF}'` 31 | alias_file=~/.${shell_type}rc 32 | alias_rm=`cat $alias_file|grep ^"alias rm="` 33 | return_value=$? 34 | #echo return_value: $return_value 35 | #echo alias_rm: $alias_rm 36 | ###如果不存在rm alias,则生成 37 | if [[ $return_value -ne 0 ]] ;then 38 | echo first time to run rmtrash 39 | echo "alias rm=/bin/rmtrash.sh" >>$alias_file && source $alias_file 40 | ###如果存在rm alias,且不是指向rmtrash的,则注释掉,区分linux 和mac 41 | elif [[ "$alias_rm" != "alias rm=/bin/rmtrash.sh" ]];then 42 | echo already has alias rm,and must commit out 43 | if [[ $os_type == Darwin ]];then 44 | sed -i .bak 's/^alias\ rm=/#alias\ rm=/g' $alias_file && \ 45 | echo "alias rm=/bin/rmtrash.sh" >>$alias_file && \ 46 | source $alias_file 47 | elif [[ $os_type == Linux ]];then 48 | sed -i.bak 's/^alias\ rm=/#alias\ rm=/g' $alias_file && \ 49 | echo "alias rm=/bin/rmtrash.sh" >>$alias_file && \ 50 | source $alias_file 51 | fi 52 | fi 53 | 54 | ####function define 55 | ###usage function 56 | rm_usage () { 57 | cat <> $trash_log && \ 110 | echo -e "\033[31m\033[05m $file is deleted from $file_fullpath\033[0m" 111 | #cat $trash_log 112 | fi 113 | 114 | #fi 115 | ###done 116 | } 117 | 118 | ###rm list function 119 | rm_list () { 120 | echo ---------------------------- 121 | echo list trash_dir contents: 122 | ls $trash_dir 123 | } 124 | 125 | 126 | ###rm restore function 127 | rm_restore () { 128 | echo ---------------------------- 129 | echo -en "请选择要恢复的文件名(多个文件中间空格分隔,取消ctl+c):" 130 | read reply 131 | for file in $reply ;do 132 | ###判断原始位置的是否有同名文件存在 133 | originalpath=`cat $trash_log|grep /$file$|awk '{print $6}'` 134 | 135 | echo $originalpath 136 | 137 | if [[ -a $originalpath ]];then 138 | echo -en "originalpath:$originalpath already exists. continue overwrite or not(y/n):" 139 | read ack 140 | if [[ $ack == y ]];then 141 | echo restore: 142 | elif [[ $ack == n ]];then 143 | echo bye && exit 144 | else 145 | echo 输入非法 && exit 146 | fi 147 | fi 148 | ### 149 | mv $trash_dir$file $originalpath && \ 150 | ###linux和mac下sed的用法有细微差别,故需通过操作系统类型进行选择对应的sed格式 151 | if [[ $os_type == Darwin ]];then 152 | sed -i .bak "/\/$file$/d" $trash_log 153 | echo os_type=Darwin 154 | elif [[ $os_type == Linux ]];then 155 | sed -i.bak "/\/$file$/d" $trash_log 156 | echo os_type=Linux 157 | fi && \ 158 | echo -e "\033[32m\033[05m$file restore ok to originalpath=$originalpath\033[0m" 159 | done 160 | } 161 | 162 | ### rm show delete log function 163 | rm_infolog () { 164 | echo ---------------------------- 165 | echo detailed deleted file log: 166 | cat $trash_log 167 | } 168 | 169 | 170 | ###rm empty trash function 171 | rm_empty () { 172 | echo ---------------------------- 173 | echo -en "empty trash,all backups in trash will be deleted, continue or not(y/n):" 174 | read ack 175 | if [[ $ack == y ]];then 176 | echo begin to empty trash: 177 | elif [[ $ack == n ]];then 178 | echo bye && exit 179 | else 180 | echo 输入非法 && exit 181 | fi 182 | if [[ -d ${trash_dir} ]] 183 | then 184 | /bin/rm -fr ${trash_dir} && \ 185 | echo >$trash_log && \ 186 | echo -e "\033[31m\033[05m The trash bin has been emptyed\033[0m" 187 | else 188 | echo "trash_dir is not exists" 189 | fi 190 | } 191 | 192 | ###rm delete function 193 | rm_delete () { 194 | echo ---------------------------- 195 | echo -en "请选择trash中要删除的文件名(多个文件中间空格分隔,取消ctl+c):" 196 | read reply 197 | for file in $reply ;do 198 | ###if file exist then delete it from trash 199 | if [[ -a ${trash_dir}$file ]];then 200 | /bin/rm -fr ${trash_dir}$file && \ 201 | ###linux和mac下sed的用法有细微差别,故需通过操作系统类型进行选择对应的sed格式 202 | if [[ $os_type == Darwin ]];then 203 | sed -i .bak "/\/$file$/d" $trash_log 204 | echo os_type=Darwin 205 | elif [[ $os_type == Linux ]];then 206 | sed -i.bak "/\/$file$/d" $trash_log 207 | echo os_type=Linux 208 | fi && \ 209 | echo -e "\033[32m\033[05m$file is deleted from trash ${trash_dir}$file \033[0m" 210 | else 211 | echo $file is not exist in $trash_dir 212 | fi 213 | done 214 | } 215 | 216 | ###清空回收站中30天之前执行rm删除过的文件 217 | rm_delete_by_30_days () { 218 | rm_mv_30_days_ago_timestamp=$1 219 | ###30*24*3600=2592000 220 | #30_days_by_seconds=2592000 221 | #cat $trash_log|awk 'BEGIN{30_days_by_seconds=2592000}{if()}' 222 | awk 'END{ 223 | print 时间差:$2-2592000 224 | {if ($2-2592000>100) print dayu} 225 | } 226 | ' $trash_log 227 | } 228 | 229 | ###跨分区的问题 230 | 231 | #####主程序开始 232 | ###参数个数为0,输出help 233 | if [ $# -eq 0 ] ;then rm_usage ;fi 234 | ###根据用户输入选项执行相应动作 235 | ###通过非显示的方式(加入fr选项,但在case里不做匹配操作,遇到含-fr/-rf/-f/-r时直接删除)支持很多用户的使用习惯rm -fr file,rm -rf file 236 | while getopts lRiecdhfr option ;do 237 | case "$option" in 238 | l) rm_list;; 239 | R) rm_list 240 | rm_restore;; 241 | i) rm_infolog;; 242 | h) rm_usage;; 243 | e) rm_empty;; 244 | c) rm_delete_by_30_days;; 245 | d) rm_list 246 | rm_delete;; 247 | \?)rm_usage 248 | exit 1;; 249 | esac 250 | done 251 | shift $((OPTIND-1)) 252 | 253 | ###将文件名的参数依次传递给rm_mv函数 254 | while [ $# -ne 0 ];do 255 | file=$1 256 | echo file=$file 257 | rm_mv 258 | shift 259 | done 260 | 261 | 262 | -------------------------------------------------------------------------------- /09_screen/README.md: -------------------------------------------------------------------------------- 1 | # 开启screen 状态栏 2 | 3 | * [适用系统](#适用系统) 4 | * [使用说明](#使用说明) 5 | * [安装](#安装) 6 | * [screen 使用](#screen-使用) 7 | 8 | ## 适用系统 9 | 10 | > * Linux 11 | 12 | ## 使用说明 13 | 14 | ### 安装 15 | 16 | ``` 17 | #curl -o screen.sh https://raw.githubusercontent.com/BillWang139967/linux_tools/master/09_screen/screen.sh 18 | #bash screen.sh 19 | ``` 20 | ### screen 使用 21 | 22 | > * C-a c 创建一个新的运行shell的窗口并切换到该窗口 23 | > * C-a C-a 切换到之前显示的窗口 24 | > * C-a n 切换到下一个窗口 25 | > * C-a p 切换到前一个窗口 26 | > * C-a d 断开所有 screen 终端,返回 screen 执行前状态,但 screen 内所有终端的任务都在执行 27 | -------------------------------------------------------------------------------- /09_screen/screen.sh: -------------------------------------------------------------------------------- 1 | ######################################################################### 2 | # File Name: screen.sh 3 | # Author: meetbill 4 | # mail: meetbill@163.com 5 | # Created Time: 2016-12-07 23:17:51 6 | ######################################################################### 7 | #!/bin/bash 8 | 9 | cat > ~/.screenrc << EOF 10 | # meetbill 11 | # meetbill@163.com 12 | hardstatus on 13 | hardstatus alwayslastline 14 | hardstatus string "%{= G}%-Lw%{= .Y}%50> %n*%f %t%{= G}%+Lw%< %{= G}%-=%D %c:%s %m/%d/%Y" 15 | 16 | # 关闭screen的startup message 17 | startup_message off 18 | 19 | # 关闭闪屏 20 | vbell off 21 | autodetach on 22 | msgwait 1 23 | shell bash 24 | termcapinfo xterm|xterms|xs|rxvt|urxvt|tila ti@:te@ 25 | EOF 26 | 27 | -------------------------------------------------------------------------------- /10_rebuild_centos/rebuild_centos6.x_X64_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #拷贝系统安装所需的软件包 3 | #author:王斌 4 | 5 | SYSTEM_DIR=/home/centos 6 | SYSTEM_NAME=itnihaoOS 7 | ISO_MOUNT_POIONT1=/mnt/cd1 8 | ISO_MOUNT_POIONT2=/mnt/cd2 9 | 10 | mount_ISO (){ 11 | mkdir ${ISO_MOUNT_POIONT1} 12 | mkdir ${ISO_MOUNT_POIONT2} 13 | mkdir ${SYSTEM_DIR}/Packages -p 14 | mkdir /home/source 15 | echo "请确保光驱里面有ISO文件,且可以被挂载" 16 | echo "请输入Y/y继续,任意键则退出运行" 17 | read ret 18 | [ ${ret} != "Y" -a ${ret} != "y" ] && exit 1 19 | echo "echo 默认情况,挂载的是/dev/cdrom到${ISO_MOUNT_POIONT1}" 20 | ls ${ISO_MOUNT_POIONT1} |grep Packages 21 | if [ "$?" == 0 ] 22 | then 23 | echo "光驱已经挂载" 24 | else 25 | echo "正在尝试挂载本地光驱到/mnt/cd1,请稍等片刻" 26 | mount /dev/cdrom ${ISO_MOUNT_POIONT1} 27 | ls ${ISO_MOUNT_POIONT1} |grep Packages 28 | if [ "$?" != 0 ] 29 | then 30 | echo "光盘挂载不成功,请手动重新挂载,或者尝试本地ISO挂载" 31 | echo "请输入本地ISO的路径:" 32 | read ret 33 | ls ${ret} 34 | [ "$?" != 0 ] && echo "本地ISO不存在或者路径错误,退出运行" && exit 1 35 | [ "$?" == 0 ] && mount -o loop ${ret} ${ISO_MOUNT_POIONT1} 36 | fi 37 | fi 38 | } 39 | 40 | 41 | copy_ISO_file (){ 42 | awk '{print $2}' install.log |sed -e '/^$/d' -e 's/^ //g'|grep -v FINISHED|grep -v ":" >/home/source/packges.list 43 | for packges in $(cat /home/source/packges.list) 44 | do 45 | cp ${ISO_MOUNT_POIONT1}/Packages/$packges* ${SYSTEM_DIR}/Packages 46 | [ $? != 0 ] && echo "copy $packges is faied!"&& cp ${ISO_MOUNT_POIONT2}/Packages/$packges* ${SYSTEM_DIR}/Packages 47 | [ $? != 0 ] && echo "$packges is not exist in ${ISO_MOUNT_POIONT2}/Packages/" 48 | done 49 | rsync -a --exclude=Packages ${ISO_MOUNT_POIONT1}/ ${SYSTEM_DIR} 50 | } 51 | 52 | 53 | rebuild_repo_xml (){ 54 | yum -y install createrepo mkisofs 55 | cd ${SYSTEM_DIR} 56 | declare -x discinfo=$(head -1 .discinfo) 57 | ##########################centos6.3_X64############################### 58 | #mv ${SYSTEM_DIR}/repodata/*x86_64-comps.xml ${SYSTEM_DIR}/repodata/comps.xml 59 | #createrepo -g ${SYSTEM_DIR}/repodata/comps.xml ${SYSTEM_DIR} 60 | #createrepo -u "media://$discinfo" -g ${SYSTEM_DIR}/repodata/comps.xml ${SYSTEM_DIR} 61 | ###################################################################### 62 | 63 | 64 | ##########################centos6.4_X64############################### 65 | mv ${SYSTEM_DIR}/repodata/*x86_64-comps.xml ${SYSTEM_DIR}/repodata/c6-x86_64-comps.xml 66 | createrepo -g ${SYSTEM_DIR}/repodata/c6-x86_64-comps.xml ${SYSTEM_DIR} 67 | createrepo -u "media://$discinfo" -g ${SYSTEM_DIR}/repodata/c6-x86_64-comps.xml ${SYSTEM_DIR} 68 | 69 | #mkisofs -o ${SYSTEM_NAME}.iso -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -R -J -v -V itnihao -T ${SYSTEM_DIR} 70 | } 71 | 72 | isolinux_cfg (){ 73 | cat > ${SYSTEM_DIR}/isolinux/isolinux.cfg < ${SYSTEM_DIR}/isolinux/ks.cfg <" --checklist "" [ ] . . . 5 | 6 | 7 | VERSION=$(whiptail --title "Linux Distro version" --checklist \ 8 | "What distro are you running?" 15 60 4 \ 9 | "Mint" "Basic usage" ON \ 10 | "Ubuntu" "Desktop usage" OFF \ 11 | "Debian" "Desktop & Server" OFF \ 12 | "CentOS" "Server usage" OFF 3>&1 1>&2 2>&3) 13 | 14 | exitstatus=$? 15 | 16 | if [ $exitstatus = 0 ]; then 17 | echo "The chosen distro is:" $VERSION 18 | else 19 | echo "You chose Cancel." 20 | fi 21 | -------------------------------------------------------------------------------- /11_shell_common/shell_whiptail/input-box.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Syntax 4 | # whiptail --title "" --inputbox "" 5 | 6 | 7 | MACHINE=$(whiptail --title "Configure profile" --inputbox "What is your Computer Name?" 10 60 Ubuntu 3>&1 1>&2 2>&3) 8 | 9 | exitstatus=$? 10 | if [ $exitstatus = 0 ]; then 11 | echo "Your Computer Name is:" $MACHINE 12 | else 13 | echo "You chose Cancel." 14 | fi 15 | -------------------------------------------------------------------------------- /11_shell_common/shell_whiptail/menu-box.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Syntax 4 | # whiptail --title "" --menu "" [ ] . . . 5 | 6 | OPTIONS=$(whiptail --title "Package Selection" --menu "Choose your package" 15 60 4 \ 7 | "1" "Minimal install" \ 8 | "2" "Server install" \ 9 | "3" "Web-server install" \ 10 | "4" "Openstack install" \ 11 | "5" "custom install" 3>&1 1>&2 2>&3) 12 | 13 | exitstatus=$? 14 | 15 | if [ $exitstatus = 0 ]; then 16 | echo "Your selected option:" $OPTIONS 17 | else 18 | echo "You chose cancel." 19 | fi 20 | -------------------------------------------------------------------------------- /11_shell_common/shell_whiptail/password-box.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # syntax 4 | # whiptail --title "" --passwordbox "" 5 | 6 | PASSWD=$(whiptail --title "Configure Password" --passwordbox "Enter your password here and choose OK to continue." 10 60 3>&1 1>&2 2>&3) 7 | 8 | exitstatus=$? 9 | 10 | if [ $exitstatus=0 ]; then 11 | echo "Your password is:" $PASSWD 12 | else 13 | echo "You chose Cancel." 14 | fi 15 | -------------------------------------------------------------------------------- /11_shell_common/shell_whiptail/progress-bar.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Syntax 4 | # whiptail --gauge "" 5 | 6 | { 7 | for ((i=0; i<=100; i+=20)); do 8 | sleep 1 9 | echo $i 10 | done 11 | } | whiptail --gauge "please wait while installing" 6 60 0 12 | 13 | -------------------------------------------------------------------------------- /11_shell_common/shell_whiptail/radiolist.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Syntax 4 | # whiptail --title "" --radiolist "" [ ] . . . 5 | 6 | VERSION=$(whiptail --title "Linux Distro version" --radiolist \ 7 | "What distro are you running?" 15 60 4 \ 8 | "Mint" "Basic usage" ON \ 9 | "Ubuntu" "Desktop usage" OFF \ 10 | "Debian" "Desktop & Server" OFF \ 11 | "CentOS" "Server usage" OFF 3>&1 1>&2 2>&3) 12 | 13 | exitstatus=$? 14 | 15 | if [ $exitstatus = 0 ]; then 16 | echo "The chosen distro is:" $VERSION 17 | else 18 | echo "You chose Cancel." 19 | fi 20 | -------------------------------------------------------------------------------- /11_shell_common/shell_whiptail/yes-no.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Syntax 4 | # whiptail --title "" --yesno "" 5 | 6 | 7 | if (whiptail --title "Select Option" --yesno "Choose Between Yes and No." 10 60) then 8 | echo "You chose Yes. Exit status was $?." 9 | else 10 | echo "You chose No. Exit status was $?." 11 | fi 12 | -------------------------------------------------------------------------------- /11_shell_common/shell_whiptail/yes-no2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Syntax 4 | # whiptail --title "" --yesno "" 5 | 6 | # Customize Yes and No buttons 7 | # customize the text for Yes and No buttons with "--yes-button" and "--no-button" options 8 | 9 | 10 | if (whiptail --title "Select Distro Option" --yes-button "Debian" --no-button "Arch-Linux" --yesno "Which do yo like better?" 10 60) then 11 | echo "You chose Debian Exit status was $?." 12 | else 13 | echo "You chose Arch-Linux. Exit status was $?." 14 | fi 15 | -------------------------------------------------------------------------------- /11_shell_common/trap_err/README.md: -------------------------------------------------------------------------------- 1 | ## trap_err 2 | 3 | 默认的 trap 处理,包括 trap ERR 是不继承到子 shell 里的 4 | 5 | > * 子 shell 6 | > * ssh 远程命令的状态 7 | 8 | 如果想要让 trap ERR 在子 shell 中生效,则需要在执行脚本的时候,使用 -E 参数执行脚本 9 | 10 | 即 11 | 12 | `bash -E trap_err.sh` 13 | -------------------------------------------------------------------------------- /11_shell_common/trap_err/trap_err.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ######################################################################### 3 | # File Name: trap_err.sh 4 | # Author: meetbill 5 | # mail: meetbill@163.com 6 | # Created Time: 2018-01-19 09:30:20 7 | ######################################################################### 8 | #!/bin/bash 9 | FILENAME=$0 10 | #定义捕捉ERR伪信号的函数 11 | ERRTRAP() 12 | { 13 | echo "[FILE:${FILENAME}] [LINE:$1] Error: Command or function exited with status $?" 14 | } 15 | 16 | fun_will_fail() 17 | { 18 | #函数返回非零值表示错误 19 | return 1 20 | } 21 | 22 | fun_will_succed() 23 | { 24 | #返回0表示函数执行成功 25 | return 0 26 | } 27 | 28 | fun_sub_will_fail() 29 | { 30 | jjjjj 31 | return 0 32 | } 33 | 34 | #命令或者函数产生的每一个错误都将产生一个ERR伪信号 35 | #这里执行trap命令是希望通过函数ERRTRAP扑捉这个ERR伪信号 36 | trap 'ERRTRAP $LINENO' ERR 37 | 38 | #模拟一个失败的命令 39 | command_not_exist 2>/dev/null 40 | 41 | #模拟一个成功执行的函数 42 | fun_will_succed 43 | 44 | #模拟一个失败了的函数 45 | fun_will_fail 46 | 47 | #模拟一个失败了的子函数 ,需要执行脚本的时候通过 -E 参数进行捕获子程序的 ERR 48 | fun_sub_will_fail 49 | 50 | exit 0 51 | -------------------------------------------------------------------------------- /12_blogger/README.md: -------------------------------------------------------------------------------- 1 | # 简介 2 | 3 | 4 | * [使用方法举例](#使用方法举例) 5 | * [导入 log](#导入-log) 6 | * [logXXX 语句](#logxxx-语句) 7 | * [设置日志级别](#设置日志级别) 8 | * [throw 语句](#throw-语句) 9 | * [my_echo 与 my_echo_error 语句](#my_echo-与-my_echo_error-语句) 10 | * [日志路径与日志文件滚动](#日志路径与日志文件滚动) 11 | 12 | 13 | 14 | 通过简单的封装,这个小 shell 可以提供诸如: 15 | 16 | > * 1. log_info,log_debug 等多级别日志输出 17 | > * 2. 日志记录带有时间戳和日志级别 18 | > * 3. 将日志输出到指定文件 19 | > * 4. 日志文件按日期进行归档 20 | > * 5. 抛出异常 21 | 22 | 您通过下面的语句,: 23 | 24 | ``` 25 | log_info hello, world 26 | log_debug "hello, world" # 推荐将所有的内容用双引号包围 27 | ``` 28 | 输出内容举例如下: 29 | 30 | ``` 31 | 2015-08-26 20:12:21 [test.sh] (INFO) hello, world 32 | 2015-08-26 20:12:21 [test.sh] (DEBUG) hello, world 33 | ``` 34 | 35 | # 使用方法举例 36 | ## 导入 log 37 | 在您的 shell 开头导入即可,可以参考 /test/test.sh 的中的用法: 38 | 39 | ``` 40 | source ./b_lib/log.sh 41 | ``` 42 | 43 | ## logXXX 语句 44 | log 提供了四个日志级别的方法,他们分别是 45 | 46 | 1. `log_debug` 47 | 2. `log_info` 48 | 3. `log_warn` 49 | 4. `log_error` 50 | 51 | 用法很简单,所有的参数都会被当做日志内容记录,比如: 52 | 53 | ``` 54 | log_info hello, world 55 | log_debug "hello, world" # 推荐将所有的内容用双引号包围 56 | ``` 57 | 输出内容举例如下: 58 | 59 | ``` 60 | 2015-08-26 20:03:18 [test.sh] (INFO) hello, this log_info 61 | 2015-08-26 20:12:21 [test.sh] (DEBUG) hello, log_debug 62 | 2015-08-26 20:12:21 [test.sh] (INFO) hello, log_info 63 | 2015-08-26 20:12:21 [test.sh] (WARN) hello, log_warn 64 | 2015-08-26 20:12:21 [test.sh] (ERROR) hello, log_error 65 | 2015-08-26 20:12:21 [test.sh] (ECHO) hello, my_echo 66 | 2015-08-26 20:12:21 [test.sh] (ECHO_ERROR) hello, my_echo_error 67 | 2015-08-26 20:13:26 [test.sh] (DEBUG) hello, log_debug 68 | ``` 69 | 70 | ## 设置日志级别 71 | log 支持 6 个日志级别,含义与 Apache 日志框架类似: 72 | 73 | > * 1. ALL 74 | > * 2. DEBUG 75 | > * 3. INFO 76 | > * 4. WARN 77 | > * 5. ERROR 78 | > * 6. OFF 79 | 80 | 如果要设置指定的日志级别,请在导入 log 之后,export 变量`LOG_LEVEL`,可设置为如下预置常量: 81 | 82 | ``` 83 | LOG_LEVEL_ALL 84 | LOG_LEVEL_DEBUG 85 | LOG_LEVEL_INFO 86 | LOG_LEVEL_WARN 87 | LOG_LEVEL_ERROR 88 | LOG_LEVEL_OFF 89 | ``` 90 | 91 | ## throw 语句 92 | `throw`语句类似 java 语言中抛异常。通过使用`throw`语句,达到类似抛异常的效果。比如: 93 | 94 | ``` 95 | throw "ParamsNumberException: need 2 params" 96 | ``` 97 | 使用 throw 语句,程序将在 stderr 输出上述语句,同时在日志文件以 LOG_LEVEL_ERROR 级别记录。最后程序会意退出码 1 退出。 98 | 99 | ## my_echo 与 my_echo_error 语句 100 | `my_echo`和`my_echo_error`与 shell 的`echo`语句类似,但有两点增强: 101 | 1. `my_echo`和`my_echo_error`不仅会输出到控制台,还会输出到日志文件。 102 | 2. `my_echo_error`的输出是 stdErr 103 | 104 | ## 日志路径与日志文件滚动 105 | 默认程序的输出日志路径是`/tmp/slog`,并在此目录下面生成已当前日期命名的日志文件,类似如下: 106 | 107 | ``` 108 | -rw-r--r-- 1 maoshuai wheel 1839 8 25 23:48 log_20150825.log 109 | -rw-r--r-- 1 maoshuai wheel 1839 8 26 20:32 log_20150826.log 110 | ``` 111 | 当然,你可以通过 export 变量`SIMPLE_LOG_DIR`指定你的日志路径,替换上述默认值。比如:`export SIMPLE_LOG_DIR=/var/log`,则所有日志都打印到`/var/log`目录下面 112 | -------------------------------------------------------------------------------- /12_blogger/b_lib/log.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ######################################################################### 3 | # File Name: log.sh 4 | # Author: meetbill 5 | # mail: meetbill@163.com 6 | # Created Time: 2019-06-12 22:48:11 7 | ######################################################################### 8 | 9 | # 日志级别常量,大于这个常量的才会打印 10 | LOG_LEVEL_ALL=-9000 11 | LOG_LEVEL_DEBUG=100 12 | LOG_LEVEL_INFO=200 13 | LOG_LEVEL_WARN=300 14 | LOG_LEVEL_ERROR=400 15 | LOG_LEVEL_OFF=9000 16 | 17 | ##############################日志工具类 18 | # 19 | # 抛异常 20 | 21 | # 日志级别 22 | # 23 | # -1 所有日志 24 | # 25 | # 默认不输出。要打开debug,可以在调用时export这个变量 26 | if [[ -z "$LOG_LEVEL" ]];then 27 | LOG_LEVEL=$LOG_LEVEL_ALL 28 | fi 29 | # 日志文件目录 30 | if [[ -z "$SIMPLE_LOG_DIR" ]];then 31 | SIMPLE_LOG_DIR=/tmp/slog # 避免不同的用户部署时公用文件 32 | fi 33 | 34 | # # 获取logger名称 35 | loggerName=$0 36 | 37 | # 根据日期获取当天日志名称 38 | function get_log_file() { 39 | if [ ! -e $SIMPLE_LOG_DIR ];then 40 | mkdir -p $SIMPLE_LOG_DIR 41 | fi 42 | local log_date=$(date +"%Y%m%d") 43 | local today_log_file=$SIMPLE_LOG_DIR/log_${log_date}.log 44 | if [ ! -e $today_log_file ];then 45 | touch $today_log_file 46 | fi 47 | echo $today_log_file 48 | } 49 | 50 | # 抛异常 51 | function throw() { 52 | if [ $# -ne 0 ];then 53 | my_echo_error "$*" 54 | log_error "$*" 55 | fi 56 | exit 1 57 | } 58 | 59 | # 代替echo,输出到标准输出 60 | function my_echo() { 61 | echo "$*" 62 | echo `date +%Y-%m-%d\ %H:%M:%S` [$loggerName]' (ECHO) '"$*" >> `get_log_file` 63 | } 64 | 65 | # 代替echo,输出到标准错误输出 66 | function my_echo_error() { 67 | echo "(ERROR)" "$*" >&2 68 | echo `date +%Y-%m-%d\ %H:%M:%S` [$loggerName]' (ECHO_ERROR) '"$*" >> `get_log_file` 69 | } 70 | 71 | function log_debug() { 72 | if [ $LOG_LEVEL -le $LOG_LEVEL_DEBUG ];then 73 | echo `date +%Y-%m-%d\ %H:%M:%S` [$loggerName]' (DEBUG) '"$*" >> `get_log_file` 74 | fi 75 | } 76 | 77 | function log_info() { 78 | if [ $LOG_LEVEL -le $LOG_LEVEL_INFO ];then 79 | echo `date +%Y-%m-%d\ %H:%M:%S` [$loggerName]' (INFO) '"$*" >> `get_log_file` 80 | fi 81 | } 82 | 83 | function log_warn() { 84 | if [ $LOG_LEVEL -le $LOG_LEVEL_WARN ];then 85 | echo `date +%Y-%m-%d\ %H:%M:%S` [$loggerName]' (WARN) '"$*" >> `get_log_file` 86 | fi 87 | } 88 | 89 | function log_error() { 90 | if [ $LOG_LEVEL -le $LOG_LEVEL_ERROR ];then 91 | echo `date +%Y-%m-%d\ %H:%M:%S` [$loggerName]' (ERROR) '"$*" >> `get_log_file` 92 | fi 93 | } 94 | -------------------------------------------------------------------------------- /12_blogger/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ######################################################################### 3 | # File Name: test.sh 4 | # Author: meetbill 5 | # mail: meetbill@163.com 6 | # Created Time: 2019-06-12 22:54:51 7 | ######################################################################### 8 | 9 | # 导入log.sh 10 | source ./b_lib/log.sh 11 | # 设置日志存储路径 12 | export SIMPLE_LOG_DIR=./log 13 | 14 | # 调用方法 15 | log_info [LINE]:${LINENO} hello, world 16 | log_debug "[LINE]:${LINENO} hello, log_debug" 17 | log_info "[LINE]:${LINENO} hello, log_info" 18 | log_warn "[LINE]:${LINENO} hello, log_warn" 19 | log_error "[LINE]:${LINENO} hello, log_error" 20 | 21 | my_echo "[LINE]:${LINENO} hello, my_echo" 22 | my_echo_error "[LINE]:${LINENO} hello, my_echo_error" 23 | 24 | throw "[LINE]:${LINENO} Arguments Number Error" 25 | -------------------------------------------------------------------------------- /13_mount_file/README.md: -------------------------------------------------------------------------------- 1 | ## 挂载文件 2 | 3 | > * 创建文件(truncate 可以将文件缩减或者扩展为指定大小,若文件不存在则创建) 4 | > * truncate -s size file_path 5 | > * 挂载文件 6 | > * mount -o loop 文件 挂载目录 7 | -------------------------------------------------------------------------------- /13_mount_file/mount_file.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ######################################################################### 3 | # File Name: mount_file.sh 4 | # Author: meetbill 5 | # mail: meetbill@163.com 6 | # Created Time: 2018-01-29 20:02:23 7 | ######################################################################### 8 | 9 | host=$(hostname) 10 | disk1=${host}sn1_test 11 | disk2=${host}sn2_test 12 | disk3=${host}sn3_test 13 | 14 | DISK_LIST="$disk1 $disk2 $disk3" 15 | 16 | function mount_all() { 17 | for disk in $DISK_LIST;do 18 | sudo mkdir -p /vols/${disk} 19 | truncate -s 1000M /dev/${disk} 20 | mkfs.xfs -f /dev/${disk} 21 | sudo mount -o loop /dev/${disk} /vols/${disk} 22 | sudo mkdir -p /vols/${disk}/${disk}/spare 23 | done 24 | } 25 | 26 | function umount_all() { 27 | for disk in $DISK_LIST;do 28 | umount /vols/${disk} 29 | rm /vols/${disk} -rf 30 | rm /vols/bad_disks.json -rf 31 | done 32 | } 33 | 34 | function usage() { 35 | echo "$0 mount_all" 36 | echo "$0 umount_all" 37 | exit -1 38 | } 39 | 40 | case $1 in 41 | "mount_all") 42 | mount_all;; 43 | "umount_all") 44 | umount_all;; 45 | *) 46 | usage;; 47 | esac 48 | -------------------------------------------------------------------------------- /14_daemon/README.md: -------------------------------------------------------------------------------- 1 | ## shell 服务管理 2 | 3 | 4 | * [1 场景](#1-场景) 5 | * [1.1 简易版服务管理程序](#11-简易版服务管理程序) 6 | * [1.2 远端执行耗时命令](#12-远端执行耗时命令) 7 | * [2 使用](#2-使用) 8 | * [2.1 修改文件](#21-修改文件) 9 | * [2.2 使用](#22-使用) 10 | * [2.3 外部调用此脚本查询进程状态](#23-外部调用此脚本查询进程状态) 11 | * [3 版本](#3-版本) 12 | 13 | 14 | 15 | ## 1 场景 16 | ### 1.1 简易版服务管理程序 17 | 18 | 用于将服务进行启动,停止,重启,查看运行状态 19 | 20 | ### 1.2 远端执行耗时命令 21 | 22 | 比如要在远程的服务器上执行 `sleep 120`,直接执行`ssh ip command`(直接这样执行时,命令会等待子进程退出) 无法批量操作效果,其原因是 ssh 需要确定命令不再有任何的输入输出,并且能有确切的返回值 23 | 24 | 这个时候可以将 `sleep 120` 放到 run.sh 中完成 25 | 26 | ## 2 使用 27 | 28 | ### 2.1 修改文件 29 | 30 | > * 将 run.sh 中 `DISP_NAME="cherry_app"` 部分修改为启动程序应用名 31 | > * 将 run.sh 中 `MAIN_FILE="sleep 120"` 部分修改为 `MAIN_FILE= 执行的命令` 32 | > * 将 run.sh 中 `MAIN_FILE_current=${MAIN_FILE}` 检测进程是否存在的关键字(默认与 MAIN_FILE 变量相同) 33 | 34 | ### 2.2 使用 35 | 36 | ``` 37 | Usage: run.sh {start|stop|restart|status} 38 | start Start cherry_app processes. 39 | stop Kill all cherry_app processes. 40 | restart Kill all cherry_app processes and start again. 41 | status Show cherry_app processes status. 42 | version Show run.sh script version. 43 | ``` 44 | ### 2.3 外部调用此脚本查询进程状态 45 | 46 | > status 输出的信息包含颜色,是隐藏字符 47 | ``` 48 | $sh run.sh status | cat -v 49 | ^[[1;91m0^[[0m cherry_app processes runing. 50 | ``` 51 | > 查询方法 52 | ``` 53 | bash run.sh status | grep processes | grep m0 > /dev/null && echo ERR || echo OK 54 | ``` 55 | 56 | ## 3 版本 57 | 58 | > * 1.0.0.3 2019-06-13 『更新』启动脚本兼容绝对路径启动 59 | > * 1.0.0.2 2018-07-02 『更新』将启动进程程序与进程标识符进行分离,以适配执行程序与进程标识不同的场景以及需要更换启动路径时场景 60 | > * 1.0.0.1 2018-04-27 初始版本 61 | -------------------------------------------------------------------------------- /14_daemon/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ######################################################################### 3 | # File Name: run.sh 4 | # Author: meetbill 5 | # mail: meetbill@163.com 6 | # Created Time: 2018-04-27 10:36:55 7 | # Update Time: 2018-07-02 16:02:33 8 | ######################################################################### 9 | 10 | CUR_DIR=$(cd `dirname $0`; pwd) 11 | cd ${CUR_DIR} 12 | DISP_NAME="cherry_app" 13 | MAIN_FILE="sleep 120" 14 | MAIN_FILE_current=${MAIN_FILE} 15 | STDOUT="${CUR_DIR}/__stdout" 16 | # Consts 17 | RED='\033[1;91m' 18 | GREN='\033[1;92m' 19 | WITE='\033[1;97m' 20 | NC='\033[0m' 21 | VERSION="1.0.0.3" 22 | 23 | # Global vailables 24 | PROC_COUNT="0" 25 | function count_proc() 26 | { 27 | PROC_COUNT=$(ps -ef | grep "${MAIN_FILE_current}" | grep -vc grep) 28 | } 29 | function list_proc() 30 | { 31 | ps -ef | grep -v grep | grep --color "${MAIN_FILE_current}" 32 | } 33 | function list_proc_pids() 34 | { 35 | ps -ef | grep "${MAIN_FILE_current}" | grep -v grep | awk '{print $2}' 36 | } 37 | 38 | function start_procs() 39 | { 40 | printf "Starting $DISP_NAME processes" 41 | count_proc 42 | if [ $PROC_COUNT \> 0 ]; then 43 | echo 44 | list_proc 45 | echo -e ${RED}"\n[ERROR]" ${NC}"Start $DISP_NAME failed, processes already runing." 46 | exit -1 47 | fi 48 | 49 | $MAIN_FILE 1>$STDOUT 2>&1 & 50 | 51 | sleep 1 52 | list_proc 53 | count_proc 54 | if [ $PROC_COUNT == 0 ]; then 55 | echo -e ${RED}"\n[ERROR]" ${NC}"Start $DISP_NAME failed." 56 | exit -1 57 | fi 58 | 59 | echo -e ${GREN}"\n[OK]" ${NC}"$DISP_NAME start succesfully." 60 | } 61 | 62 | function stop_procs() 63 | { 64 | printf "Stoping $DISP_NAME" 65 | count_proc 66 | if [ ${PROC_COUNT} -eq 0 ]; then 67 | echo -e ${RED}"\n[ERROR]" ${NC}"$DISP_NAME process not found." 68 | exit -1 69 | fi 70 | 71 | kill -15 $(list_proc_pids) 72 | count_proc 73 | while [ ${PROC_COUNT} -ne 0 ]; do 74 | printf "." 75 | sleep 0.2 76 | count_proc 77 | done 78 | echo -e ${GREN}"\n[OK]" ${NC}"$DISP_NAME stop succesfully." 79 | } 80 | 81 | function status_procs() 82 | { 83 | count_proc 84 | echo -e ${RED}${PROC_COUNT}${NC} "$DISP_NAME processes runing." 85 | } 86 | 87 | function version_script() 88 | { 89 | echo "[version]:${VERSION}" 90 | } 91 | 92 | MODE=${1} 93 | case ${MODE} in 94 | "start") 95 | start_procs 96 | ;; 97 | 98 | "stop") 99 | stop_procs 100 | ;; 101 | 102 | "restart") 103 | stop_procs 104 | start_procs 105 | ;; 106 | 107 | "status") 108 | status_procs 109 | ;; 110 | "version") 111 | version_script 112 | ;; 113 | *) 114 | # usage 115 | echo -e "\nUsage: $0 {start|stop|restart|status}" 116 | echo -e ${WITE}" start "${NC}"Start $DISP_NAME processes." 117 | echo -e ${WITE}" stop "${NC}"Kill all $DISP_NAME processes." 118 | echo -e ${WITE}" restart "${NC}"Kill all $DISP_NAME processes and start again." 119 | echo -e ${WITE}" status "${NC}"Show $DISP_NAME processes status." 120 | echo -e ${WITE}" version "${NC}"Show $0 script version.\n" 121 | exit 1 122 | ;; 123 | esac 124 | -------------------------------------------------------------------------------- /15_tcpcopy/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: 4 | subtitle: 5 | date: 2018-07-03 11:15:39 6 | category: 7 | author: meetbill 8 | tags: 9 | - 10 | --- 11 | 12 | ## tcpcopy 13 | 14 | > * 此工具用于远程管理 tcpcopy 和 intercept 15 | 16 | ## 使用 17 | 18 | > * (1) 本地编译 tcpcopy [编译 tcpcopy 工具](https://github.com/meetbill/shell_menu),将生成后的目录 /root/tcp_copy 中的所有文件放到本目录下的 tcp_copy 19 | > * (2) 使用 run.sh 20 | 21 | ``` 22 | Usage: run.sh {start|stop|restart|status} 23 | start source_ip_port dest_ip_portStart processes. 24 | copy_stop source_ip_port Kill all processes. 25 | copy_status source_ip_port Show processes status. 26 | cept_stop dest_ip_port Kill all processes. 27 | cept_status dest_ip_port Show processes status. 28 | ``` 29 | ## 附录 30 | 最后的目录结构如下 31 | ``` 32 | ├── run.sh 33 | └── tcp_copy 34 | ├── bin 35 | ├── cept.sh 36 | ├── conf 37 | ├── copy.sh 38 | ├── include 39 | ├── lib 40 | ├── logs 41 | ├── sbin 42 | ├── share 43 | ``` 44 | -------------------------------------------------------------------------------- /15_tcpcopy/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ######################################################################### 3 | # File Name: run.sh 4 | # Author: meetbill 5 | # mail: meetbill@163.com 6 | # Created Time: 2018-06-27 14:23:26 7 | ######################################################################### 8 | #set -e 9 | #source ./config 10 | 11 | source_ip_port=$1 12 | dest_ip_port=$2 13 | multiple=10 14 | 15 | CUR_DIR=$(cd `dirname $0`; pwd) 16 | cd ${CUR_DIR} 17 | RED='\e[1;91m' 18 | GREN='\e[1;92m' 19 | WITE='\e[1;97m' 20 | NC='\e[0m' 21 | f_yellow='\e[00;33m' 22 | f_red='\e[00;31m' 23 | f_green='\e[00;32m' 24 | f_reset='\e[00;0m' 25 | 26 | function p_warn { 27 | echo -e "${f_yellow}[wrn]${f_reset} ${1}" 28 | } 29 | 30 | function p_err { 31 | echo -e "${f_red}[err]${f_reset} ${1}" 32 | } 33 | 34 | function p_ok { 35 | echo -e "${f_green}[ok ]${f_reset} ${1}" 36 | } 37 | function start_procs() 38 | { 39 | source_ip_port=$1 40 | dest_ip_port=$2 41 | [[ -z ${dest_ip_port} ]] && p_err "not found dest_ip_port" && exit 1 42 | 43 | dest_ip=$(echo ${dest_ip_port} | awk -F : '{print $1}') 44 | dest_port=$(echo ${dest_ip_port} | awk -F : '{print $2}') 45 | cept_status=$(ssh root@${dest_ip} "ls -l | grep tcp_copy|wc -l") 46 | if [[ "w${cept_status}" == "w0" ]] 47 | then 48 | scp -qr ./tcp_copy root@${dest_ip}:~ 49 | fi 50 | cept_status=$(ssh root@${dest_ip} "ps -ef | grep intercept | grep -v grep | wc -l") 51 | if [[ "w${cept_status}" == "w0" ]] 52 | then 53 | ssh root@${dest_ip} "bash /root/tcp_copy/cept.sh start ${dest_port}" 54 | fi 55 | 56 | 57 | [[ -z ${source_ip_port} ]] && p_err "not found source_ip_port" && exit 1 58 | [[ -z ${multiple} ]] && p_err "not found multiple" && exit 1 59 | source_ip=$(echo ${source_ip_port} | awk -F : '{print $1}') 60 | source_port=$(echo ${source_ip_port} | awk -F : '{print $2}') 61 | copy_status=$(ssh root@${source_ip} "ls -l | grep tcp_copy|wc -l") 62 | if [[ "w${copy_status}" == "w0" ]] 63 | then 64 | scp -qr ./tcp_copy root@${source_ip}:~ 65 | fi 66 | ssh root@${source_ip} "bash /root/tcp_copy/copy.sh start ${source_port} ${dest_ip} ${dest_port} ${multiple}" 67 | } 68 | 69 | function copy_status_procs() 70 | { 71 | source_ip_port=$1 72 | [[ -z ${source_ip_port} ]] && p_err "not found source_ip_port" && exit 1 73 | source_ip=$(echo ${source_ip_port} | awk -F : '{print $1}') 74 | source_port=$(echo ${source_ip_port} | awk -F : '{print $2}') 75 | copy_status=$(ssh root@${source_ip} "ls -l | grep tcp_copy|wc -l") 76 | if [[ "w${copy_status}" == "w0" ]] 77 | then 78 | scp -qr ./tcp_copy root@${source_ip}:~ 79 | fi 80 | ssh root@${source_ip} "bash /root/tcp_copy/copy.sh status" 81 | } 82 | function copy_stop_procs() 83 | { 84 | source_ip_port=$1 85 | [[ -z ${source_ip_port} ]] && p_err "not found source_ip_port" && exit 1 86 | source_ip=$(echo ${source_ip_port} | awk -F : '{print $1}') 87 | source_port=$(echo ${source_ip_port} | awk -F : '{print $2}') 88 | copy_status=$(ssh root@${source_ip} "ls -l | grep tcp_copy|wc -l") 89 | ssh root@${source_ip} "bash /root/tcp_copy/copy.sh stop" 90 | } 91 | function cept_status_procs() 92 | { 93 | dest_ip_port=$1 94 | [[ -z ${dest_ip_port} ]] && p_err "not found dest_ip_port" && exit 1 95 | dest_ip=$(echo ${dest_ip_port} | awk -F : '{print $1}') 96 | dest_port=$(echo ${dest_ip_port} | awk -F : '{print $2}') 97 | copy_status=$(ssh root@${dest_ip} "ls -l | grep tcp_copy|wc -l") 98 | if [[ "w${copy_status}" == "w0" ]] 99 | then 100 | scp -qr ./tcp_copy root@${source_ip}:~ 101 | sleep 3 102 | fi 103 | ssh root@${dest_ip} "bash /root/tcp_copy/cept.sh status" 104 | } 105 | function cept_stop_procs() 106 | { 107 | dest_ip_port=$1 108 | [[ -z ${dest_ip_port} ]] && p_err "not found dest_ip_port" && exit 1 109 | dest_ip=$(echo ${dest_ip_port} | awk -F : '{print $1}') 110 | dest_port=$(echo ${dest_ip_port} | awk -F : '{print $2}') 111 | copy_status=$(ssh root@${dest_ip} "ls -l | grep tcp_copy|wc -l") 112 | ssh root@${dest_ip} "bash /root/tcp_copy/cept.sh stop" 113 | } 114 | 115 | MODE=${1} 116 | source_ip_port=${2} 117 | dest_ip_port=${3} 118 | case ${MODE} in 119 | "start") 120 | start_procs $source_ip_port $dest_ip_port 121 | ;; 122 | 123 | "copy_stop") 124 | copy_stop_procs $source_ip_port 125 | ;; 126 | 127 | "copy_status") 128 | copy_status_procs $source_ip_port 129 | ;; 130 | "cept_stop") 131 | cept_stop_procs $source_ip_port 132 | ;; 133 | 134 | "cept_status") 135 | cept_status_procs $source_ip_port 136 | ;; 137 | 138 | *) 139 | # usage 140 | echo -e "\nUsage: $0 {start|stop|restart|status}" 141 | echo -e ${WITE}" start source_ip_port dest_ip_port "${NC}"Start $DISP_NAME processes." 142 | echo -e ${WITE}" copy_stop source_ip_port "${NC}"Kill all $DISP_NAME processes." 143 | echo -e ${WITE}" copy_status source_ip_port "${NC}"Show $DISP_NAME processes status." 144 | echo -e ${WITE}" cept_stop dest_ip_port "${NC}"Kill all $DISP_NAME processes." 145 | echo -e ${WITE}" cept_status dest_ip_port "${NC}"Show $DISP_NAME processes status.\n" 146 | exit 1 147 | ;; 148 | esac 149 | -------------------------------------------------------------------------------- /15_tcpcopy/tcp_copy/cept.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ######################################################################### 3 | # File Name: run.sh 4 | # Author: meetbill 5 | # mail: meetbill@163.com 6 | # Created Time: 2018-04-27 10:36:55 7 | ######################################################################### 8 | 9 | ROOT_PATH=`S=\`readlink "$0"\`; [ -z "$S" ] && S=$0; dirname $S` 10 | cd ${ROOT_PATH} 11 | DISP_NAME="inter_cept" 12 | EXEC_FILE="./sbin/intercept" 13 | MAIN_FILE="intercept" 14 | STDOUT="./__stdout" 15 | # Consts 16 | RED='\e[1;91m' 17 | GREN='\e[1;92m' 18 | WITE='\e[1;97m' 19 | NC='\e[0m' 20 | 21 | # Global vailables 22 | PROC_COUNT="0" 23 | function count_proc() 24 | { 25 | PROC_COUNT=$(ps -ef | grep "$MAIN_FILE" | grep -vc grep) 26 | } 27 | function list_proc() 28 | { 29 | ps -ef | grep -v grep | grep --color "$MAIN_FILE" 30 | } 31 | function list_proc_pids() 32 | { 33 | ps -ef | grep "$MAIN_FILE" | grep -v grep | awk '{print $2}' 34 | } 35 | 36 | function start_procs() 37 | { 38 | cept_port=$1 39 | [[ -z ${cept_port} ]] && echo "not found port" && exit -1 40 | export LD_LIBRARY_PATH=${ROOT_PATH}/lib:$LD_LIBRARY_PATH 41 | printf "Starting $DISP_NAME processes" 42 | count_proc 43 | if [ $PROC_COUNT \> 0 ]; then 44 | echo 45 | list_proc 46 | echo -e ${RED}"\n[ERROR]" ${NC}"Start $DISP_NAME failed, processes already runing." 47 | exit -1 48 | fi 49 | 50 | $EXEC_FILE -i xgbe0 -F "tcp and src port $cept_port" -d 1>$STDOUT 2>&1 & 51 | 52 | sleep 1 53 | list_proc 54 | count_proc 55 | if [ $PROC_COUNT == 0 ]; then 56 | echo -e ${RED}"\n[ERROR]" ${NC}"Start $DISP_NAME failed." 57 | exit -1 58 | fi 59 | 60 | echo -e ${GREN}"\n[OK]" ${NC}"$DISP_NAME start succesfully." 61 | } 62 | 63 | function stop_procs() 64 | { 65 | printf "Stoping $DISP_NAME" 66 | count_proc 67 | if [ ${PROC_COUNT} -eq 0 ]; then 68 | echo -e ${RED}"\n[ERROR]" ${NC}"$DISP_NAME process not found." 69 | exit -1 70 | fi 71 | 72 | kill -15 $(list_proc_pids) 73 | count_proc 74 | while [ ${PROC_COUNT} -ne 0 ]; do 75 | printf "." 76 | sleep 0.2 77 | count_proc 78 | done 79 | echo -e ${GREN}"\n[OK]" ${NC}"$DISP_NAME stop succesfully." 80 | } 81 | 82 | function status_procs() 83 | { 84 | count_proc 85 | echo -e ${RED}${PROC_COUNT}${NC} "$DISP_NAME processes runing." 86 | } 87 | 88 | MODE=${1} 89 | port=${2} 90 | case ${MODE} in 91 | "start") 92 | start_procs $port 93 | ;; 94 | 95 | "stop") 96 | stop_procs 97 | ;; 98 | 99 | "restart") 100 | stop_procs 101 | start_procs 102 | ;; 103 | 104 | "status") 105 | status_procs 106 | ;; 107 | 108 | *) 109 | # usage 110 | echo -e "\nUsage: $0 {start|stop|restart|status}" 111 | echo -e ${WITE}" start port "${NC}"Start $DISP_NAME processes." 112 | echo -e ${WITE}" stop "${NC}"Kill all $DISP_NAME processes." 113 | echo -e ${WITE}" restart "${NC}"Kill all $DISP_NAME processes and start again." 114 | echo -e ${WITE}" status "${NC}"Show $DISP_NAME processes status.\n" 115 | exit 1 116 | ;; 117 | esac 118 | -------------------------------------------------------------------------------- /15_tcpcopy/tcp_copy/copy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ######################################################################### 3 | # File Name: run.sh 4 | # Author: meetbill 5 | # mail: meetbill@163.com 6 | # Created Time: 2018-04-27 10:36:55 7 | ######################################################################### 8 | 9 | ROOT_PATH=`S=\`readlink "$0"\`; [ -z "$S" ] && S=$0; dirname $S` 10 | cd ${ROOT_PATH} 11 | DISP_NAME="tcp_copy" 12 | EXEC_FILE="./sbin/tcpcopy" 13 | MAIN_FILE="tcpcopy" 14 | STDOUT="./__stdout" 15 | # Consts 16 | RED='\e[1;91m' 17 | GREN='\e[1;92m' 18 | WITE='\e[1;97m' 19 | NC='\e[0m' 20 | 21 | # Global vailables 22 | PROC_COUNT="0" 23 | function count_proc() 24 | { 25 | PROC_COUNT=$(ps -ef | grep "$MAIN_FILE" | grep -vc grep) 26 | } 27 | function list_proc() 28 | { 29 | ps -ef | grep -v grep | grep --color "$MAIN_FILE" 30 | } 31 | function list_proc_pids() 32 | { 33 | ps -ef | grep "$MAIN_FILE" | grep -v grep | awk '{print $2}' 34 | } 35 | 36 | function start_procs() 37 | { 38 | source_port=$1 39 | dest_ip=$2 40 | dest_port=$3 41 | multiple=$4 42 | [[ -z ${source_port} ]] && echo "not found source port" && exit -1 43 | [[ -z ${dest_ip} ]] && echo "not found dest_ip " && exit -1 44 | [[ -z ${dest_port} ]] && echo "not found dest_port " && exit -1 45 | [[ -z ${multiple} ]] && echo "not found multiple " && exit -1 46 | printf "Starting $DISP_NAME processes" 47 | count_proc 48 | if [ $PROC_COUNT \> 0 ]; then 49 | echo 50 | list_proc 51 | echo -e ${RED}"\n[ERROR]" ${NC}"Start $DISP_NAME failed, processes already runing." 52 | exit -1 53 | fi 54 | 55 | $EXEC_FILE -x ${source_port}-${dest_ip}:${dest_port} -s ${dest_ip} -c 192.168.2.x -n ${multiple} -d 1>$STDOUT 2>&1 & 56 | 57 | sleep 1 58 | list_proc 59 | count_proc 60 | if [ $PROC_COUNT == 0 ]; then 61 | echo -e ${RED}"\n[ERROR]" ${NC}"Start $DISP_NAME failed." 62 | exit -1 63 | fi 64 | 65 | echo -e ${GREN}"\n[OK]" ${NC}"$DISP_NAME start succesfully." 66 | } 67 | 68 | function stop_procs() 69 | { 70 | printf "Stoping $DISP_NAME" 71 | count_proc 72 | if [ ${PROC_COUNT} -eq 0 ]; then 73 | echo -e ${RED}"\n[ERROR]" ${NC}"$DISP_NAME process not found." 74 | exit -1 75 | fi 76 | 77 | kill -15 $(list_proc_pids) 78 | count_proc 79 | while [ ${PROC_COUNT} -ne 0 ]; do 80 | printf "." 81 | sleep 0.2 82 | count_proc 83 | done 84 | echo -e ${GREN}"\n[OK]" ${NC}"$DISP_NAME stop succesfully." 85 | } 86 | 87 | function status_procs() 88 | { 89 | count_proc 90 | echo -e ${RED}${PROC_COUNT}${NC} "$DISP_NAME processes runing." 91 | } 92 | 93 | MODE=${1} 94 | source_port=${2} 95 | dest_ip=${3} 96 | dest_port=${4} 97 | multiple=${5} 98 | case ${MODE} in 99 | "start") 100 | start_procs $source_port $dest_ip $dest_port ${multiple} 101 | ;; 102 | 103 | "stop") 104 | stop_procs 105 | ;; 106 | 107 | "restart") 108 | stop_procs 109 | start_procs 110 | ;; 111 | 112 | "status") 113 | status_procs 114 | ;; 115 | 116 | *) 117 | # usage 118 | echo -e "\nUsage: $0 {start|stop|restart|status}" 119 | echo -e ${WITE}" start source_port dest_ip dest_port multiple"${NC}"Start $DISP_NAME processes." 120 | echo -e ${WITE}" stop "${NC}"Kill all $DISP_NAME processes." 121 | echo -e ${WITE}" restart "${NC}"Kill all $DISP_NAME processes and start again." 122 | echo -e ${WITE}" status "${NC}"Show $DISP_NAME processes status.\n" 123 | exit 1 124 | ;; 125 | esac 126 | -------------------------------------------------------------------------------- /16_truncate/README.md: -------------------------------------------------------------------------------- 1 | ## 使用 truncate 安全地删除大文件 2 | > 代码 3 | ``` 4 | #!/bin/bash 5 | 6 | ###每次递减10G进行删除### 7 | # 假设文件有 200G 以上 8 | for i in `seq 200 -10 10` 9 | do 10 | echo "truncate $i G......" 11 | truncate -s ${i}G /data/aaa.log 12 | sleep 3 13 | done 14 | ``` 15 | > 注意: 16 | ``` 17 | truncate必须是文件,不能对目录做truncate操作 18 | ``` 19 | > 参数 20 | ``` 21 | -s 22 | KB 1000, K 1024, MB 1000*1000, M 1024*1024, and so on for G, T, P, E, Z, Y. 23 | ``` 24 | -------------------------------------------------------------------------------- /17_logrotate/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: shell logrotate 4 | subtitle: 5 | date: 2019-09-07 16:31:21 6 | category: 日志切割和清理 7 | author: meetbill 8 | tags: 9 | - 10 | --- 11 | 12 | ## shell logrotate 13 | 14 | 15 | 16 | 17 | * [1 功能](#1-功能) 18 | * [2 使用](#2-使用) 19 | * [2.1 启动管理](#21-启动管理) 20 | * [2.2 配置管理](#22-配置管理) 21 | * [2.3 logrotate 日志](#23-logrotate-日志) 22 | * [3 番外](#3-番外) 23 | * [find 中的 mtime 参数](#find-中的-mtime-参数) 24 | 25 | 26 | 27 | ## 1 功能 28 | 29 | 每小时进行切割和清理通用日志 30 | 31 | ## 2 使用 32 | ### 2.1 启动管理 33 | 34 | ``` 35 | $sh log_control.sh 36 | 37 | Usage: log_control.sh {start|stop|restart|status} 38 | start Start logrotate processes. 39 | stop Kill all logrotate processes. 40 | restart Kill all logrotate processes and start again. 41 | status Show logrotate processes status. 42 | version Show log_control.sh script version. 43 | ``` 44 | 45 | ### 2.2 配置管理 46 | 47 | logrotate_exe.sh 48 | ``` 49 | # app 主目录,即以此脚本为 base 路径,进行设置 APP_HOME 50 | APP_HOME=${CUR_DIR}/.. 51 | LOG_PATH="${APP_HOME}/log" 52 | 53 | #任务 54 | LOG_KEEP_TIME="7" # 保存天数 55 | LOG_PATH="${NGINX_LOG_PATH}/nginx.access_log" # 日志路径 56 | LOG_BACK_DIR=$(dirname ${LOG_PATH}) # 备份日志的路径 57 | END_CMD="" # 需要执行的额外命令 58 | log_cut # 日志切割和清理 59 | ``` 60 | ### 2.3 logrotate 日志 61 | 62 | > 启动日志 63 | ``` 64 | log/__logrotate_stdout 65 | ``` 66 | > 运行日志 67 | ``` 68 | 默认存放在此目录的 log 目录 69 | ``` 70 | 71 | ## 3 番外 72 | 73 | ### find 中的 mtime 参数 74 | 75 | > find . –mtime n 76 | ``` 77 | File waslast modified n*24 hours ago. 78 | 最后一次修改发生在距离当前时间n*24小时至(n+1)*24 小时 79 | ``` 80 | 81 | > find . –mtime +n 82 | 83 | ``` 84 | 最后一次修改发生在n+1天以前,距离当前时间为(n+1)*24小时或者更早 85 | ``` 86 | 87 | > find . –mtime –n 88 | ``` 89 | 最后一次修改发生在n天以内,距离当前时间为n*24小时以内 90 | ``` 91 | -------------------------------------------------------------------------------- /17_logrotate/log_control.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ######################################################################### 3 | # File Name: run.sh 4 | # Author: meetbill 5 | # mail: meetbill@163.com 6 | # Created Time: 2018-04-27 10:36:55 7 | # Update Time: 2018-07-02 16:02:33 8 | ######################################################################### 9 | 10 | CUR_DIR=$(cd `dirname $0`; pwd) 11 | cd ${CUR_DIR} 12 | DISP_NAME="logrotate" 13 | MAIN_FILE="bash ${CUR_DIR}/logrotate_loop.sh" 14 | MAIN_FILE_current=${MAIN_FILE} 15 | mkdir -p ${CUR_DIR}/log 16 | STDOUT="${CUR_DIR}/log/__logrotate_stdout" 17 | # Consts 18 | RED='\033[1;91m' 19 | GREN='\033[1;92m' 20 | WITE='\033[1;97m' 21 | NC='\033[0m' 22 | VERSION="1.0.0.3" 23 | 24 | # Global vailables 25 | PROC_COUNT="0" 26 | function count_proc() 27 | { 28 | PROC_COUNT=$(ps -ef | grep "${MAIN_FILE_current}" | grep -vc grep) 29 | } 30 | function list_proc() 31 | { 32 | ps -ef | grep -v grep | grep --color "${MAIN_FILE_current}" 33 | } 34 | function list_proc_pids() 35 | { 36 | ps -ef | grep "${MAIN_FILE_current}" | grep -v grep | awk '{print $2}' 37 | } 38 | 39 | function start_procs() 40 | { 41 | printf "Starting $DISP_NAME processes" 42 | count_proc 43 | if [ $PROC_COUNT \> 0 ]; then 44 | echo 45 | list_proc 46 | echo -e ${RED}"\n[ERROR]" ${NC}"Start $DISP_NAME failed, processes already runing." 47 | exit -1 48 | fi 49 | 50 | $MAIN_FILE 1>$STDOUT 2>&1 & 51 | 52 | sleep 1 53 | list_proc 54 | count_proc 55 | if [ $PROC_COUNT == 0 ]; then 56 | echo -e ${RED}"\n[ERROR]" ${NC}"Start $DISP_NAME failed." 57 | exit -1 58 | fi 59 | 60 | echo -e ${GREN}"\n[OK]" ${NC}"$DISP_NAME start succesfully." 61 | } 62 | 63 | function stop_procs() 64 | { 65 | printf "Stoping $DISP_NAME" 66 | count_proc 67 | if [ ${PROC_COUNT} -eq 0 ]; then 68 | echo -e ${RED}"\n[ERROR]" ${NC}"$DISP_NAME process not found." 69 | exit -1 70 | fi 71 | 72 | kill -15 $(list_proc_pids) 73 | count_proc 74 | while [ ${PROC_COUNT} -ne 0 ]; do 75 | printf "." 76 | sleep 0.2 77 | count_proc 78 | done 79 | echo -e ${GREN}"\n[OK]" ${NC}"$DISP_NAME stop succesfully." 80 | } 81 | 82 | function status_procs() 83 | { 84 | count_proc 85 | echo -e ${RED}${PROC_COUNT}${NC} "$DISP_NAME processes runing." 86 | } 87 | 88 | function version_script() 89 | { 90 | echo "[version]:${VERSION}" 91 | } 92 | 93 | MODE=${1} 94 | case ${MODE} in 95 | "start") 96 | start_procs 97 | ;; 98 | 99 | "stop") 100 | stop_procs 101 | ;; 102 | 103 | "restart") 104 | stop_procs 105 | start_procs 106 | ;; 107 | 108 | "status") 109 | status_procs 110 | ;; 111 | "version") 112 | version_script 113 | ;; 114 | *) 115 | # usage 116 | echo -e "\nUsage: $0 {start|stop|restart|status}" 117 | echo -e ${WITE}" start "${NC}"Start $DISP_NAME processes." 118 | echo -e ${WITE}" stop "${NC}"Kill all $DISP_NAME processes." 119 | echo -e ${WITE}" restart "${NC}"Kill all $DISP_NAME processes and start again." 120 | echo -e ${WITE}" status "${NC}"Show $DISP_NAME processes status." 121 | echo -e ${WITE}" version "${NC}"Show $0 script version.\n" 122 | exit 1 123 | ;; 124 | esac 125 | -------------------------------------------------------------------------------- /17_logrotate/log_rotate_lib/log.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ######################################################################### 3 | # File Name: log.sh 4 | # Author: meetbill 5 | # mail: meetbill@163.com 6 | # Created Time: 2019-06-12 22:48:11 7 | ######################################################################### 8 | 9 | # 日志级别常量,大于这个常量的才会打印 10 | LOG_LEVEL_ALL=-9000 11 | LOG_LEVEL_DEBUG=100 12 | LOG_LEVEL_INFO=200 13 | LOG_LEVEL_WARN=300 14 | LOG_LEVEL_ERROR=400 15 | LOG_LEVEL_OFF=9000 16 | 17 | ##############################日志工具类 18 | # 19 | # 抛异常 20 | 21 | # 日志级别 22 | # 23 | # -1 所有日志 24 | # 25 | # 默认不输出。要打开debug,可以在调用时export这个变量 26 | if [[ -z "$LOG_LEVEL" ]];then 27 | LOG_LEVEL=$LOG_LEVEL_ALL 28 | fi 29 | # 日志文件目录 30 | if [[ -z "$SIMPLE_LOG_DIR" ]];then 31 | SIMPLE_LOG_DIR=/tmp/slog # 避免不同的用户部署时公用文件 32 | fi 33 | 34 | # # 获取logger名称 35 | loggerName=$0 36 | 37 | # 根据日期获取当天日志名称 38 | function get_log_file() { 39 | if [ ! -e $SIMPLE_LOG_DIR ];then 40 | mkdir -p $SIMPLE_LOG_DIR 41 | fi 42 | local log_date=$(date +"%Y%m%d") 43 | local today_log_file=$SIMPLE_LOG_DIR/log_${log_date}.log 44 | if [ ! -e $today_log_file ];then 45 | touch $today_log_file 46 | fi 47 | echo $today_log_file 48 | } 49 | 50 | # 抛异常 51 | function throw() { 52 | if [ $# -ne 0 ];then 53 | my_echo_error "$*" 54 | log_error "$*" 55 | fi 56 | exit 1 57 | } 58 | 59 | # 代替echo,输出到标准输出 60 | function my_echo() { 61 | echo "$*" 62 | echo `date +%Y-%m-%d\ %H:%M:%S` [$loggerName]' (ECHO) '"$*" >> `get_log_file` 63 | } 64 | 65 | # 代替echo,输出到标准错误输出 66 | function my_echo_error() { 67 | echo "(ERROR)" "$*" >&2 68 | echo `date +%Y-%m-%d\ %H:%M:%S` [$loggerName]' (ECHO_ERROR) '"$*" >> `get_log_file` 69 | } 70 | 71 | function log_debug() { 72 | if [ $LOG_LEVEL -le $LOG_LEVEL_DEBUG ];then 73 | echo `date +%Y-%m-%d\ %H:%M:%S` [$loggerName]' (DEBUG) '"$*" >> `get_log_file` 74 | fi 75 | } 76 | 77 | function log_info() { 78 | if [ $LOG_LEVEL -le $LOG_LEVEL_INFO ];then 79 | echo `date +%Y-%m-%d\ %H:%M:%S` [$loggerName]' (INFO) '"$*" >> `get_log_file` 80 | fi 81 | } 82 | 83 | function log_warn() { 84 | if [ $LOG_LEVEL -le $LOG_LEVEL_WARN ];then 85 | echo `date +%Y-%m-%d\ %H:%M:%S` [$loggerName]' (WARN) '"$*" >> `get_log_file` 86 | fi 87 | } 88 | 89 | function log_error() { 90 | if [ $LOG_LEVEL -le $LOG_LEVEL_ERROR ];then 91 | echo `date +%Y-%m-%d\ %H:%M:%S` [$loggerName]' (ERROR) '"$*" >> `get_log_file` 92 | fi 93 | } 94 | -------------------------------------------------------------------------------- /17_logrotate/log_rotate_lib/op_log_rotate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ######################################################################### 3 | # File Name: op_log_rotate.sh 4 | # Author: meetbill 5 | # mail: meetbill@163.com 6 | # Created Time: 2019-09-07 14:28:07 7 | # user defile,required 8 | # LOG_KEEP_TIME="15" 9 | # LOG_BACK_DIR="/home/work/test/log/" 10 | # LOG_PATH="/home/work/test/log/access.log" 11 | ######################################################################### 12 | 13 | END_CMD="" 14 | #default 15 | TODAY=`date +"%Y%m%d%H"` 16 | NOW=`date +"%Y-%m-%d %H:%M:%S"` 17 | 18 | function log_cut(){ 19 | if [ ! ${LOG_KEEP_TIME} ] || [ ! ${LOG_BACK_DIR} ] || [ ! ${LOG_PATH} ];then 20 | log_error "error! Variable not assigned,please check LOG_KEEP_TIME,LOG_BACK_DIR,LOG_PATH" 21 | exit 2 22 | fi 23 | log_info "[${NOW}] [log_file:$LOG_PATH] [backdir:$LOG_BACK_DIR] [keep_day:$LOG_KEEP_TIME] [end_cmd:$END_CMD] start log_cut..." 24 | log_dir=$(dirname $LOG_PATH) 25 | log_file=$(basename $LOG_PATH) 26 | cd ${log_dir} 27 | if [ $? -ne 0 ];then 28 | log_error "dir not exist:${log_dir}" 29 | exit 2 30 | fi 31 | #cut log 32 | if [ ! -f ${log_file} ]; then 33 | touch ${log_file}.${TODAY} 34 | else 35 | mv "${log_file}" "${log_file}.${TODAY}" 36 | if [ $? -ne 0 ];then 37 | log_error "mv ${log_file} ${log_file}.${TODAY} fail!" 38 | exit 4 39 | fi 40 | fi 41 | 42 | #exec reload cmd 43 | if [[ -n "${END_CMD}" ]];then 44 | log_info "END_CMD=\"${END_CMD}\",start exec..." 45 | ${END_CMD} 46 | fi 47 | 48 | #clear log 49 | for old_log_file in `find ./ -type f -name "${log_file}.20*" -mtime +"${LOG_KEEP_TIME}" ` 50 | do 51 | log_clear $old_log_file 52 | done 53 | log_info "[${NOW}] [log_file:$LOG_PATH] log_cut exec success!!!!" 54 | 55 | # 如果磁盘使用率超过 90 %,则将所有带时间戳日志进行清理 56 | ################################################# 57 | #home_used=$(df -h | grep "/home"| awk '{print $(NF-1)}' | tr -d '%') 58 | #if [[ ${home_used} -gt 90 ]];then 59 | # log_info "[${NOW}] [/home used]${home_used}% start rm Timestamped logs" 60 | # for old_log_file in `find ./ -type f -name "${log_file}.20*"` 61 | # do 62 | # log_clear $old_log_file 63 | # done 64 | #fi 65 | ################################################# 66 | } 67 | 68 | # 删除日志 69 | function log_clear(){ 70 | old_log_file=$1 71 | old_log_file_size=`du -k ${old_log_file}|awk '{print $1}'` 72 | # 日志超过 200G,则使用 truncate 进行逐渐删除 73 | if [[ ${old_log_file_size} -gt 200000000 ]];then 74 | for i in `seq 200 -10 10` 75 | do 76 | truncate -s ${i}G ${old_log_file} 77 | sleep 5 78 | done 79 | log_info "[${NOW}] [old_log_file:$old_log_file] [old_log_size:${old_log_file_size}] truncate success!!!!" 80 | fi 81 | [[ -f ${old_log_file} ]] && rm -rf ${old_log_file} 82 | log_info "[${NOW}] [old_log_file:$old_log_file] [old_log_size:${old_log_file_size}] rm success!!!!" 83 | sleep 2 84 | } 85 | -------------------------------------------------------------------------------- /17_logrotate/logrotate_exe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ######################################################################### 3 | # File Name: logrotate_exe.sh 4 | # Author: meetbill 5 | # mail: meetbill@163.com 6 | # Created Time: 2019-09-07 14:27:19 7 | # 8 | # [1] required parameter: 9 | # LOG_KEEP_TIME="10" 10 | # LOG_BACK_DIR="/home/work/test/log/" 11 | # LOG_PATH="/home/work/test/log/access.log" 12 | # END_CMD="echo kakaka" 13 | # 14 | # [2] function:log_cut log_clear 15 | # log_cut contain log_clear 16 | # 17 | # [3] tips:you have ro redefine all required parameter before add a new task!(otherwise the parameter will use the old one) 18 | ######################################################################### 19 | 20 | CUR_DIR=$(cd `dirname $0`; pwd) 21 | cd ${CUR_DIR} 22 | 23 | EXE_LOG=${CUR_DIR}/log 24 | export SIMPLE_LOG_DIR=${EXE_LOG} 25 | source ${CUR_DIR}/log_rotate_lib/log.sh 26 | source ${CUR_DIR}/log_rotate_lib/op_log_rotate.sh 27 | 28 | # 设置 APP_HOME 为当前目录的父目录 29 | APP_HOME=$(dirname $CUR_DIR) 30 | log_info "[APP_HOME:${APP_HOME}] start -----------------------------------------------------" 31 | # NGINX_PID_PATH=${APP_HOME}/log 32 | ADAPTER_LOG_PATH="${APP_HOME}/log" 33 | NUTCRACKER_LOG_PATH="${APP_HOME}/log" 34 | 35 | 36 | if [[ $? -ne 0 ]];then 37 | echo "[`date +"%Y-%m-%d %H:%M:%S"`] source ./op_log_rotate.sh fail !" 38 | exit 2; 39 | fi 40 | ######################################################### 41 | # task demo1 42 | #LOG_KEEP_TIME="7" 43 | #LOG_PATH="${NGINX_LOG_PATH}/nginx.access_log" 44 | #LOG_BACK_DIR=$(dirname ${LOG_PATH}) 45 | #END_CMD="" 46 | #log_cut 47 | # task demo2 48 | #LOG_KEEP_TIME="7" 49 | #LOG_PATH="${NGINX_LOG_PATH}/nginx.error_log" 50 | #LOG_BACK_DIR=$(dirname ${LOG_PATH}) 51 | #END_CMD="kill -USR1 `cat ${NGINX_PID_PATH}/nginx.pid`" 52 | #log_cut 53 | ######################################################### 54 | 55 | #task 1 56 | LOG_KEEP_TIME="2" 57 | LOG_PATH="${ADAPTER_LOG_PATH}/demo.log" 58 | LOG_BACK_DIR=$(dirname ${LOG_PATH}) 59 | END_CMD="" 60 | log_cut 61 | 62 | #task 2 63 | LOG_KEEP_TIME="2" 64 | LOG_PATH="${ADAPTER_LOG_PATH}/demo.log.wf" 65 | LOG_BACK_DIR=$(dirname ${LOG_PATH}) 66 | END_CMD="" 67 | 68 | log_cut 69 | #task 3 70 | LOG_KEEP_TIME="2" 71 | LOG_PATH="${NUTCRACKER_LOG_PATH}/nutcracker.log" 72 | LOG_BACK_DIR=$(dirname ${LOG_PATH}) 73 | END_CMD="kill -1 `ps -ef | grep ${APP_HOME} | grep nutcracker | grep -v grep | awk '{print $2}'`" 74 | log_cut 75 | 76 | -------------------------------------------------------------------------------- /17_logrotate/logrotate_loop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ######################################################################### 3 | # File Name: logrotate_loop.sh 4 | # Author: meetbill 5 | # mail: meetbill@163.com 6 | # Created Time: 2019-09-07 16:09:18 7 | ######################################################################### 8 | 9 | #执行一次后,sleep的时间(300 s) 10 | LOGROTATE_SLEEP=300 11 | 12 | #每次判断当前分钟数的时间间隔(60 s) 13 | CHECK_SLEEP=60 14 | 15 | function logrotate_loop() 16 | { 17 | while true; 18 | do 19 | current_minute=`date +%M` 20 | # 08的时候会报错,转成10进制 21 | current_minute=$((10#$current_minute)) 22 | if [[ $current_minute -ge 0 && $current_minute -le 2 ]] 23 | then 24 | bash ./logrotate_exe.sh 25 | sleep $LOGROTATE_SLEEP 26 | fi 27 | sleep $CHECK_SLEEP 28 | done 29 | 30 | } 31 | 32 | logrotate_loop 33 | -------------------------------------------------------------------------------- /18_opmv/opmv: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #=============================================================================== 3 | # 4 | # FILE: opmv 5 | # 6 | # USAGE: sh opmv 7 | # 8 | # DESCRIPTION: This program is used for backup current file 9 | # 10 | # OPTIONS: --- 11 | # REQUIREMENTS: --- 12 | # BUGS: --- 13 | # NOTES: --- 14 | # AUTHOR: meetbill@163.com 15 | # VERSION: 2.0 16 | # CREATED: 2020/04/15 16:33:51 PM CST 17 | # REVISION: --- 18 | #=============================================================================== 19 | 20 | cfont() 21 | { 22 | while (($#!=0)) 23 | do 24 | case $1 in 25 | -b) 26 | echo -ne " "; 27 | ;; 28 | -t) 29 | echo -ne "\t"; 30 | ;; 31 | -n) echo -ne "\n"; 32 | ;; 33 | -black) 34 | echo -ne "\033[30m"; 35 | ;; 36 | -red) 37 | echo -ne "\033[31m"; 38 | ;; 39 | -green) 40 | echo -ne "\033[32m"; 41 | ;; 42 | -yellow) 43 | echo -ne "\033[33m"; 44 | ;; 45 | -blue) 46 | echo -ne "\033[34m"; 47 | ;; 48 | -purple) 49 | echo -ne "\033[35m"; 50 | ;; 51 | -cyan) 52 | echo -ne "\033[36m"; 53 | ;; 54 | -lred) 55 | echo -ne "\033[1;31m"; 56 | ;; 57 | -lblue) 58 | echo -ne "\033[1;34m"; 59 | ;; 60 | -dblue) 61 | echo -ne "\033[1;36m"; 62 | ;; 63 | -lwhite) 64 | echo -ne "\033[1;37m"; 65 | ;; 66 | -white|-gray) echo -ne "\033[37m"; 67 | ;; 68 | -reset) 69 | echo -ne "\033[0m"; 70 | ;; 71 | -h|-help|--help) 72 | echo "Usage: cfont -color1 message1 -color2 message2 ..."; 73 | echo "eg: cfont -red [ -blue message1 message2 -red ]"; 74 | ;; 75 | *) 76 | echo -ne "$1" 77 | ;; 78 | esac 79 | shift 80 | done 81 | } 82 | 83 | #PATHBAK=$HOME/$USER.bak 84 | PWDPATH=`pwd` 85 | USER_INPUT_LIST="$*" 86 | if [ -z "$USER_INPUT_LIST" ] 87 | then 88 | cfont -red "Usage: $0 xx.conf" -n -reset 89 | exit 1 90 | 91 | else 92 | WORK_DIR=$HOME 93 | PATHBAK=$WORK_DIR/opdir/backup 94 | 95 | DATETIME=$(date +%Y%m%d%H%M%S) 96 | 97 | #check the user input 98 | #######################################for -i 99 | nocreat="0" 100 | #######################################for -i 101 | for USER_INPUT in $USER_INPUT_LIST 102 | do 103 | 104 | #######################################for -i 105 | if [ "$USER_INPUT" == "-i" ] 106 | then 107 | nocreat="1" 108 | USER_INPUT_LIST=$(for itmp in $USER_INPUT_LIST; do if [ "$itmp" != "$USER_INPUT" ];then echo -n "$itmp ";fi ;done) 109 | #USER_INPUT_LIST=$(echo "$USER_INPUT_LIST"|sed -e "s/$USER_INPUT//") 110 | #######################################for -i 111 | else 112 | [[ -f $USER_INPUT || -d $USER_INPUT ]] 113 | if [ "$?" -ne "0" ] 114 | then 115 | echo "$USER_INPUT" is not a file or a dirctory! 116 | # USER_INPUT_LIST=$(echo "$USER_INPUT_LIST"|sed -e "s/$USER_INPUT//") 117 | # USER_INPUT_LIST=$(for itmp in "$USER_INPUT_LIST"; do echo -n "$itmp " |grep -v "$USER_INPUT";done) 118 | USER_INPUT_LIST=$(for itmp in $USER_INPUT_LIST; do if [ "$itmp" != "$USER_INPUT" ];then echo -n "$itmp ";fi ;done) 119 | # exit 1 120 | 121 | fi 122 | fi 123 | 124 | done 125 | if [ -z "$USER_INPUT_LIST" ] 126 | then 127 | echo "Usage: $0 appui.conf" 128 | exit 1 129 | 130 | fi 131 | #pass the check above,then continue 132 | for USER_INPUT in $USER_INPUT_LIST 133 | do 134 | # echo $USER_INPUT 135 | cfont -dblue "$USER_INPUT" -n -reset 136 | #get file or dir name 137 | BASENAME=$(basename $USER_INPUT) 138 | 139 | #get absolute path name 140 | FLAG_FILE=0 141 | FLAG_DIR=0 142 | if [ -f "$USER_INPUT" ] 143 | then 144 | DIRNAME=$(dirname $USER_INPUT) 145 | FLAG_FILE=1 146 | elif [ -d "$USER_INPUT" ] 147 | then 148 | DIRNAME="$USER_INPUT" 149 | FLAG_DIR=1 150 | else 151 | DIRNAME=$(dirname $USER_INPUT) 152 | fi 153 | 154 | ADIRNAME=$(cd $DIRNAME;pwd;cd - &>/dev/null) 155 | 156 | #gen the backup full path 157 | 158 | BAKPATH=$PATHBAK/$(echo $ADIRNAME |awk 'BEGIN{FS="/";N=4;}{if(NF>=N){while (N<=NF){if(N==4){printf "%s.%s.%s/%s/","opmv",$N,"'$DATETIME'",$N} else {printf "%s/",$N;} N++}}else{printf "%s.%s.%s/%s/","opmv",$NF,"'$DATETIME'",$NF;}}') 159 | 160 | #######################################for -i 161 | if [ "$nocreat" -eq "1" ] 162 | then 163 | BAKPATH=$PATHBAK/$(echo $ADIRNAME |awk 'BEGIN{FS="/";N=4;}{if(NF>=N){while (N<=NF){if(N==4){printf "%s.%s.%s/%s/","opmv",$N,"bak",$N} else {printf "%s/",$N;} N++}}else{printf "%s.%s.%s/%s/","opmv",$NF,"bak",$NF;}}') 164 | fi 165 | #######################################for -i 166 | 167 | 168 | #common used name , path 169 | MOD_NAME=$(echo $ADIRNAME |awk 'BEGIN{FS="/"}{if(NF>=4){printf "%s",$4}else{printf "%s",$NF}}') 170 | MOD_PATH=$(echo $ADIRNAME |awk 'BEGIN{FS="/";N=4;}{if(NF>=N){while (N<=NF) {printf "%s/",$N; N++}}else{printf "%s/",$NF}}') 171 | 172 | #used for opdiff opmv etc. or easy reading 173 | 174 | LNPATH1=$PATHBAK/opmv.$MOD_NAME.$DATETIME 175 | LNPATH2=$PATHBAK/opmv.$MOD_NAME.bak 176 | 177 | # BAKPATHLN1=$PATHBAK/$(echo $ADIRNAME |awk 'BEGIN{FS="/";N=4;}{printf "%s.%s",$N,"'$DATETIME'";}') 178 | # BAKPATHLN2=$PATHBAK/$(echo $ADIRNAME |awk 'BEGIN{FS="/";N=4;}{printf "%s.bak",$N;}') 179 | 180 | 181 | #begin to cp files 182 | 183 | 184 | if [ -f $BAKPATH/$BASENAME ] 185 | then 186 | mkdir -p $BAKPATH 187 | cd $PATHBAK/ 188 | 189 | mv $BAKPATH/$BASENAME $BAKPATH/$BASENAME.$DATETIME 190 | fi 191 | 192 | if [ "$FLAG_FILE" -eq 1 ] 193 | then 194 | mkdir -p $BAKPATH 195 | cd $PATHBAK/ 196 | SOURCE_FILE="$ADIRNAME/$BASENAME" 197 | DEST_FILE="$BAKPATH/$BASENAME" 198 | elif [ "$FLAG_DIR" -eq 1 ] 199 | then 200 | FLAG_NULL=$(ls $ADIRNAME 2>/dev/null|wc -l) 201 | SOURCE_FILE="$ADIRNAME" 202 | DEST_FILE=$(echo $BAKPATH |awk 'BEGIN{FS="/";N=1}{while (N/dev/null 226 | 227 | if [ $return -eq "0" ] 228 | then 229 | if [ "$FLAG_FILE" -eq 1 ] 230 | then 231 | #SOURCE_FILE="$ADIRNAME/$BASENAME" 232 | #DEST_FILE="$BAKPATH/$BASENAME" 233 | #md5sum $BAKPATH/$BASENAME $LNPATH2/$MOD_PATH/$BASENAME 234 | file_size=$(du -sk $BAKPATH/$BASENAME |awk '{print $1}') 235 | if [ $file_size -lt 102400 ] 236 | then 237 | md5sum_source=$(md5sum $BAKPATH/$BASENAME |awk '{print $1}') 238 | cfont -lwhite "$md5sum_source $BAKPATH/$BASENAME" -n -reset 239 | else 240 | size_source=$(du -sk $BAKPATH/$BASENAME|awk '{print $1}') 241 | cfont -lwhite "$size_source $BAKPATH/$BASENAME" -n -reset 242 | fi 243 | 244 | #elif [ -d $BAKPATH/$BASENAME ] 245 | elif [ "$FLAG_DIR" -eq 1 ] 246 | then 247 | #SOURCE_FILE="$ADIRNAME" 248 | #DEST_FILE="$BAKPATH" 249 | #size_source=$(du -sk $SOURCE_FILE|awk '{print $1}') 250 | size_dest=$(du -sk $BAKPATH|awk '{print $1}') 251 | # du -sk $BAKPATH/$BASENAME 252 | #size_source=$(du -sk $BAKPATH/$BASENAME|awk '{print $1}') 253 | cfont -lwhite "$size_dest $BAKPATH" -n -reset 254 | fi 255 | else 256 | cfont -red "mv $ADIRNAME/$BASENAME $BAKPATH/$BASENAME FAILED!!" -n -reset 257 | fi 258 | 259 | done 260 | fi 261 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | {one line to give the program's name and a brief idea of what it does.} 635 | Copyright (C) {year} {name of author} 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | {project} Copyright (C) {year} {fullname} 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # linux_tools 2 | 3 | > * 安全 4 | > * [denyhosts](./06_denyhosts/) 简单防止 ssh 暴力破解脚本 5 | > * [audit_action](./07_audit_action/) linux 操作审计 6 | > * [linux_iptables](./04_linux_iptables/) 配置 iptables 7 | > * 磁盘 8 | > * [parted_mkfs](./01_parted_mkfs/) 批量对硬盘进行分区和格式化 9 | > * [mount_file](./13_mount_file) 将文件进行挂载 10 | > * 监控 11 | > * [raid_monitor](./02_raid_monitor/) 对 raid 进行监控 12 | > * 配置 13 | > * [keepalived_check](./03_keepalived_check/) 对 keepalived 的配置文件进行检查 14 | > * [change_hostname](./05_change_hostname/) 对 hostname 进行修改 15 | > * 易用 16 | > * [rm](./08_rm/) 开启 linux 回收站 17 | > * [screen](./09_screen/) 开启 screen 状态栏 18 | > * [opmv](./18_opmv/) 类似 Linux 回收站,将文件移动到特定备份目录 19 | > * 工具 20 | > * [rebuild_centos](./10_rebuild_centos/) 构建 centos 系统程序 21 | > * [shell_common](./11_shell_common/) 相关模板 22 | > * [daemon](./14_daemon) 管理程序工具 23 | > * [tcpcopy 管理工具](./15_tcpcopy) 24 | > * 日志 25 | > * [blogger](./12_blogger/) 记录 shell 运行日志 26 | > * [truncate](./16_truncate) 使用 truncate 安全地删除大文件 27 | > * [logrotate](./17_logrotate) 通用日志切割和清理,按照时间切割 28 | 29 | ## 相关项目 30 | 31 | > * [shell_menu](https://github.com/meetbill/shell_menu) 32 | > * [op_practice_code](https://github.com/meetbill/op_practice_code) 33 | 34 | ## 参加步骤 35 | 36 | * 在 GitHub 上 `fork` 到自己的仓库,然后 `clone` 到本地,并设置用户信息。 37 | ``` 38 | $ git clone https://github.com/meetbill/linux_tools.git 39 | $ cd linux_tools 40 | $ git config user.name "yourname" 41 | $ git config user.email "your email" 42 | ``` 43 | * 修改代码后提交,并推送到自己的仓库。 44 | ``` 45 | $ #do some change on the content 46 | $ git commit -am "Fix issue #1: change helo to hello" 47 | $ git push 48 | ``` 49 | * 在 GitHub 网站上提交 pull request。 50 | * 定期使用项目仓库内容更新自己仓库内容。 51 | ``` 52 | $ git remote add upstream https://github.com/meetbill/linux_tools.git 53 | $ git fetch upstream 54 | $ git checkout master 55 | $ git rebase upstream/master 56 | $ git push -f origin master 57 | ``` 58 | 59 | 60 | ## Stargazers over time 61 | 62 | [![Stargazers over time](https://starchart.cc/meetbill/linux_tools.svg)](https://starchart.cc/meetbill/linux_tools) 63 | 64 | --------------------------------------------------------------------------------