Linux基础知识_Shell编程笔记

时间:2023-03-09 10:03:56
Linux基础知识_Shell编程笔记

以下是一些 常用功能 , 基于 centos 6.5 x64, 也有部分centos7 64 会有提示。

# cp /etc/localtime /etc/localtime.org
# rm /etc/localtime
# ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime #启用中文支持
vim /etc/profile export LC_ALL="zh_CN.UTF-8"
export LANG="zh_CN.UTF-8"
export LC_CTYPE="zh_CN.UTF-8"
# en_US.UTF- 还原 source /etc/profile netstat -nltp # 查看进程及端口
kill - **** # 杀死指定PID的进程 # 类似于 httpd / nginx 停止接受新连接,等当前连接停止,重载配置文件,重开日志文件,重启服务
kill -USR1 pid # 开机启动界面 ########################################
vim /etc/inittab # 6.5版本以下
systemctl set-default graphical.target # 7版本 设置图形界面启动
systemctl set-default multi-user.target # 由图形界面模式更改为命令行模式
################################## useradd test
passwd test
su test # su是用来切换用户,但是之前的用户依然是登录状态.
# su不加参数是默认切到root, 缺点是用户需要知道root密码.
su - # 加了横线表示切换到root及根目录下. #### sudo 则是为普通用户临时提供root权限.
#### 当用户使用sudo命令时, 系统会寻找/etc/sudoers文件,判断该用户是否有执行sudo权限
vim /etc/sudoers # 为新用户添加sudo权限. 这样test用户才可以使用sudo 或者直接使用visudo命令 test ALL=(ALL) ALL
### 用户 主机=(谁的身份) 命令 hadoop master=NOPASSWD: /bin/ls, /bin/cat # 只允许hadoop用户在master上免密执行ls, cat命令.
### 实际环境中,管理员会给普通用户配置sudo权限. sudo在执行带有重定向符号时,需要 sh -c "" 引号括起完整命令: sudo sh -c "echo 11111 > /data/test.txt" userdel -r test
vim /etc/passwd #可以查看系统中的所有用户
root:x:::root:/root:/bin/bash
# 用户名:密码x:用户id0:组id0:描述信息root:用户根目录/root/:用户登录后的shell
# x 是表示此处为空;采用shadow passwd,影子密码在 /etc/shadow 文件 # 命令别名定义
alias drm="rm -rf" # drm 代表了命令rm -rf
unalias drm # 删除别名
alias # 查看别名 ls -lh --time-style=+"%Y-%m-%d %H:%M:%S" # 设置显示文件时间戳 ############################ network ###############################
vim /etc/sysconfig/network-scripts/ifcfg-eth0 # centos7以后 ens33
DEVICE="eth0"
BOOTPROTO="static"
HWADDR="00:0C:29:F5:05:8E"
NM_CONTROLLED="yes"
ONBOOT="yes"
TYPE="Ethernet"
IPADDR=192.168.112.10
NETMASK=255.255.255.0
GATEWAY=192.168.112.2
DNS1=192.168.112.2
##可删除HWADDR,UUID
service network restart # 重启网络服务 ##网卡更换后,可编辑 vim /etc/udev/rules.d/70-persistent-net.rules
# 将最后一条末尾改为 eth0 ,其它的网卡信息删除后保存
reboot # 重启
ifconfig # 网络信息 # CentOS7之后,如果网卡不能启动,出现“ journalctl -xe ”的提示时,执行之后有“Failed to start LSB: Bring up/down networking” 时,可尝试以下命令:
systemctl stop NetworkManager
systemctl disable NetworkManager # 关闭自带网络管理套件
systemctl start network.service
ifconfig # 如果正常则幸运解决
## 可参考:http://blog.sina.com.cn/s/blog_6253d0970102xg3o.html curl www.taobao.com # 得到某 url 内容,顺便也可以看看是否显得出中文
curl -I www.baidu.com # 返回站点响应头 Server: Tengine
# 如果有代理,也可以看到 X-Cache: 信息 netstat #网络端口监听 -a显示所有选项, -t仅显示TCP, -u仅显示UDP, -l仅列出有监听的. netstat -nltp # 查看有监听端口的进程 netstat -an |grep 'ESTABLISHED' |grep -i '8080' |wc -l # 8080的连接数 netstat -an |grep 'ESTABLISHED' |grep -i '27017' |wc -l # mongodb的连接数 netstat -an |grep 'ESTABLISHED' |wc -l # 总连接数 #修改hosts和主机名
# 修改/etc/hosts 以及/etc/sysconfig/network 文件, 分别设置不同的HOSTNAME
vim /etc/hosts
192.168.112.10 master
192.168.112.11 slave1
192.168.112.12 slave2 hostname master
vim /etc/sysconfig/network
HOSTNAME=master ### CentOS7 以上,需要执行命令:
hostnamectl set-hostname *** ### 关闭防火墙
service iptables stop
setenforce 0
chkconfig iptables off

常用命令与工具:

######################################### 资源 情况 ####################
du -hs db # 显示db文件夹总大小
du -hs # 显示当前目录大小 也可以加 --max-depth=1
df -h # disk info
df -hT # disk info with FileSystem
df -h db # 查看db文件夹所在分区的磁盘使用情况
free # Memory
top # 任务管理器
#------------------------ top -------------------------------------
top -p [PID] # 监控指定PID
top -p 765,767,768 # 监控指定的三个
top -u user # 只显示user进程
top -c # 显示详细进程信息 P # CPU百分比排序
M # 内存
T # 累积CPU时间
s # 刷新间隔
k # 结束指定进程 cat /dev/null > create_data_prod_py.log # 清空这个日志文件 > 是覆盖输出, >> 是追加输出
echo > a.log # 清空日志 ## 重定向
## (STDIN) (STDOUT) (STDERR)
date > a.txt # 是重写内容
date >> a.txt # 是附加内容
wall < /etc/issue.net # 输入重定向,广播了某文件的内容
ls /temp > ls.err # 错误重定向,出错时写入文件 数字2代表错误输出
cp -R /usr /backup/usr.bak > /bak.error # 备份出错时,保存记录 write user # 向用户user 发送消息
wall # 向所有用户发送消息 ### 管道
ll /etc | more # 将前一个命令的结果作为后一个命令的输入
ll /etc | grep init # 查看/etc下的以init筛选后的结果
ll /etc | grep init | wc -l # 管道连用,查看上面的结果有多少行. ## 命令连接符 ; && ||
pwd ; ls ; date # 就是类似于编程语言中分号的作用,命令依次执行。
ls && pwd # 逻辑与,第一个命令成功,才会执行第二个命令。失败则不执行第二个。
ls || pwd # 逻辑或,第一个命令成功,不执行第二个。失败则执行第二个。 ## 命令替换符 将后边命令的输出作为前边命令的参数
ll `which java` # 找到java后,列出目录 ## 如果要编译程序,通常需要安装依赖,可以一条命令多个组件.
yum install gcc gcc-c++ automake autoconf libtool openssl-devel pcre-devel -y
## 以下是python2.7运行MySQLdb模块时,可能用到的:
yum install gcc gcc-c++ -y
yum -y install mysql-devel
yum install python-devel
pip install --upgrade pip
pip install MySQL-python -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

压缩解压:

# tar gz xz
tar zcf a.tar.gz logs # common compress
tar Jcf a.tar.xz logs # high compress
tar zxf xxx.tar.gz # extract
tar Jxf xxx.tar.xz # extract
gzip -9 xxx.log
gzip -d xxx.log.gz # zip
yum install -y zip unzip
zip -r a.zip logs/
unzip b.zip
unzip -l b.zip # rar
cd /opt/
wget https://www.rarlab.com/rar/rarlinux-x64-5.9.0.tar.gz
tar zxf rarlinux-x64-5.9..tar.gz
ln -s /opt/rar/rar /usr/bin/rar
ln -s /opt/rar/unrar /usr/bin/unrar # 7z
yum install p7zip p7zip-plugins
7z a a.7z logs # compress
7z x a.7z # extract

定时任务:

#################################  crontab  #################################

# crontab:
crontab -l #查看当前用户的crontab内容.
crontab -r #删除定时任务配置,如果不指定用户,则删除当前用户的.
crontab -e #编辑某个用户的crontab内容. 创建时也就先执行这个命令。
#crontab格式
#分 时 日 月 周 命令
* * * /shell/upFile2HDFS.sh #每天0点执行一次 */ * * * * date >> /test/date.txt #每分钟将时间写入文件 * * * /usr/local/etc/rc.d/httpd restart #每天21:30执行一次命令 20 0,4,8,12,16,20 * * * /data/test.sh # 0:20, 4:20, ... 20:20 执行脚本 , - * * , /usr/local/etc/rc.d/httpd restart #每个周六,周日的18点到23点,每隔30分钟 # 不要忘记开启crond服务。
yum -y install crontabs # 安装
service crond start # 启动服务 nohup python -u myscript.py >> a.log & # 指定脚本在后台运行。 nohup ... & jobs -l # 可查看nohup跑的进程
ps -ef # 通过进程查看
netstat -ntp # 通过端口查看 ## --------------------- 任务切换到后台运行 ----------------------------
# 以 scp -r 复制文件为例,因为要输密码,所以不能直接 nohup ... &
scp -r A005003/ 10.170.6.117:/data/mongobak # 复制文件到远端
# 输密码,开始传送:
ctrl + z # 暂停 出现jobs列表
bg %1 # 根据jobs的列表的任务号
jobs # 是否Running
disown -h %1 # 忽略hup信号
ps -ef |grep scp
logout
#################################  建立每台电脑的互信关系  #################################
ssh-keygen         # 创建.ssh目录 ,一路回车即可.
ssh-copy-id slave1 # 复制公钥到目标主机或IP ssh root@slave1 # 测试登录 ssh root@slave2 都能成功,不用密码,则互信成功.

修改yum源:

#----------------------------------------------------------------------#
# 修改yum源为aliyun
# 先备份:
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
# 下载配置文件 注意 centos版本
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
yum makecache # 生成缓存 # 163 网址
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo
#----------------------------------------------------------------------# lsb_release -a # 查看发行版本号 如果需要安装 yum -y install redhat-lsb
uname -a # 查看内核版本
cat /etc/os-release # 查看OS发行版
cat /etc/redhat-release # 具体版本
cat /etc/issue # 查看发行版
ulimit -a # 显示目前资源限制的设定
ulimit -n # 打开文件描述符的最大值 more /etc/*release # 更多信息
getconf LONG_BIT # 系统位数
uptime # 运行时间 load avg 为1m,5m,15m的CPU均值
last # 登录日志
w # 负载与用户连接情况
cat /proc/cpuinfo # 查看cpu核数
vmstat # 查看进程、cpu、memory、交换、io、系统
last reboot # 第一行是上次重启时间
who -b # 上次重启时间 # 参考: https://www.cnblogs.com/zhangmingcheng/p/6438994.html

设置时区时间相关

date -s "2018-01-01 14:22:33" # 修改时间 参数后面加字符串
clock -w # 写入硬件时钟
date -R #显示时区
tzselect #时区向导
# 其实不考虑各个发行版的差异化, 从更底层出发的话, 修改时间时区比想象中要简单:
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime #修改时区 # centos 7
sudo timedatectl --help    # 系统时间控制台
sudo timedatectl         # 显示时间信息
sudo timedatectl set-time 15:22:22 # 设置时间
sudo timedatectl set-time "2020-05-02 09:32:50" # 包括日期时间
yum install ntp # 安装ntp服务
ntpdate pool.ntp.org # ntp对时
chkconfig ntpd on
/etc/init.d/ntpd start # centos7 改到了/sbin/ntpd
clock -w # 写入硬件时钟 vim /etc/rc.d/rc.local # 可设置开机启动项目 并且要给此文件加可执行权限 已逐渐弃用,官方建议使用systemd
#例如,在最后加上 /etc/init.d/mysqld start则可以启动mysqld # centos7 若没有ifconfig,安装网络工具
ip addr
yum -y install net-tools # centos7 可以使用以下命令,安装大多数开发工具及依赖
yum groups info "Development Tools" # 查看
yum groups install "Development Tools" # 安装
# 此外,还有部分yum命令:
yum list installed # 查看已安装的包
yum list installed |grep docker # 查找是否安装docker
yum remove -y *gnome* # 删除所有包含gnome的包及其依赖
yum remove gnome-shell-3.26.2-5.el7.x86_64 # 单独删除某个包
yum install epel-release # 使用 epel 库,这个库带有很多第三方软件 如 nginx
wget https://mirrors.aliyun.com/epel/7/x86_64/Packages/e/epel-release-7-12.noarch.rpm # 也可以手动下载国内的epel源,然后安装
rpm -Uvh epel-release-7-12.noarch.rpm
yum update          # 全部更新
yum update epel-release # 只更新指定包
yum install nginx       # 安装 nginx

rpm 命令:

rpm -qa |grep erlang      # 查找已安装的 erlang 相关软件
rpm -Uvh rabbitmq-server # U 如果有旧版则升级安装
rpm -e --nodeps erlang-stdlib-R16B-03.18.el7.x86_64 # 卸载 忽略依赖,软件包

history命令:

-c:清除命令历史;
-d:offset:删除指定命令历史;
-r:从文件读取目录历史至历史列表中;
-w:把历史列表中的命令追加至历史文件中 ~/.bash_history history 显示最近的20条命令;
! 执行第542条命令 # 添加环境变量:
export HISTCONTROL=ignoreboth # 忽略空格开头忽略重复命令
export HISTTIMEFORMAT="%F %T " # 命令带日期时间
# 查找命令
find / -name tomcat # 找tomcat # 按常人理解的日期格式
ls -lh --time-style=+"%Y-%m-%d %H:%M:%S" # 显示所有全局变量
export # shell多行注释
:<<!
被注释掉的内容
!d \cp -rf . /opt/apps/screen-frontend/dist/ # \cp表示调用原生cp命令,-rf 表示递归处理及强制覆盖不提示 . 当前目录

Vim的操作:

############# vim ###########################################
命令模式下:
)把光标移动到要复制的行上,按yy (复制当前行)
)把光标移动到要复制的位置 ,按p (粘贴到指定行)
)把光标移动到要复制的位置 ,按dd(删除当前行) 移动光标: hjkl 左下上右
ctrl+u:到文件头
ctrl+d:到文件尾
shift+h:到屏幕第一行,shift+m:到屏幕中间,shift+l:到最后一行, shift+zz 保存退出
:n 到第n 行
^ 到行首,$ 到行尾 (这两个与正则一样) 查找并高亮: /name 查找 name n下一个,N上一个
替换 :%s/原/新 # 这是全部替换
取消高亮: :noh :r! pwd # 执行这个shell并将结果插入到当前行的下一行。 撤销更改:u:取消更改
插入:a从光标后,i从光标前,o从光标下一行

:set ff      # 查看当前文本的模式类型,dos,unix
:set ff=dos  # 设置为dos模式, 也可用 sed -i 's/$/\r/'?
:set ff=unix # 设置为unix模式,也可用 sed -i 's/.$//g'

:set fileencoding  # 查看现在文本的编码
:set fenc=utf8     # 转换当前编码为utf8 cp936, gb18030 ...

列操作,比如每行开头加注释
ESC, Ctrl + v 进入visual
数字5,再下箭头,即可向下选中5行。
shift + i 插入,# 再按2次ESC,即可在所有选中行前插入#
按 d 即删除选中的部分

# Vim批量注释
ctrl+v 列编辑模式,上下移动光标,开头标记起来,按大写I(shift+i),插入注释符,比如"//",再Esc,就会全部注释
# 批量去掉注释
ctrl+v 列编辑模式,先上下,横向选中列的个数(如"//"注释符号,需要选中两列),然后按d, 就会删除注释符号 ##配置文件 vim /etc/vimrc
set nu # 行号
set ts= # tab距离4空格
set et # tab转换为真正的空格 # modeline 相当于文件格式配置
# vim:et:ts=:sw=:
############# vim end #########################################

挂载硬盘与分区 

# 先在虚拟机中添加硬盘,比如3T大小,不用关机,Centos7 可直接检测到

fdisk -l
# 可以看到 Disk /dev/vdc: .2GB vdc 表示这是第3块盘了。
# 挂载使用以下两种方式均可: #------------------------方式一: 整盘格式化,直接挂载 -------------------------
mkfs.xfs /dev/vdc
# 直接格式化整盘,没有分区。注:fdisk 默认分区最大2T
# ext4 文件系统逐渐老去,未来 xfs 将会取代。 mkdir /E
mount /dev/vdc /E
# 挂载到 /E df -h
# Filesystem Size Used Avail Use% Mounted on
# /dev/vdc .9T 89M .8T % /E
# 写入文件试试。 # 需要系统启动时自动挂载,则 vi /etc/fstab 添加一行:
/dev/vdc /E xfs defaults 1 2
# 磁盘 挂载点 文件系统 选项 0忽略/1允许dump fsck检查顺序0不检 # umount /E 不用时可以卸载 #------------------------ 方式二: 先分区再挂载 ---------------------------------
# 开始分区
fdisk /dev/vdc
m # 帮助
g # 开始创建GPT分区表(因为vdc大于2T,所以必须GPT)
n # 开始创建分区,1号,然后一路默认回车。
t # 改变分区类型
L # 找到 Linux LVM 序号
31 # 这个序号对应 Linux LVM ,每台机器可能不同,以实际为准。
w # 保存 fdisk -l # 再次查看,得到以下信息:
Disk /dev/vdc: 3221.2 GB, bytes, sectors
Disk label type: gpt
Disk identifier: 2A96EF32-3BDB-4EAB-B7DB-
# Start End Size Type Name
3T Linux filesyste mkfs.xfs -f /dev/vdc1 # 格式化为XFS,等待数秒完成
mkdir /E
mount /dev/vdc1 /E
df -h
# Filesystem Size Used Avail Use% Mounted on
# /dev/vdc1 .0T 33M .0T % /E
# /dev/vdb .8T .8T .7T % /data # 需要系统启动时自动挂载,则 vi /etc/fstab 添加一行:
/dev/vdc1 /E xfs defaults
# 磁盘 挂载点 文件系统 选项 0忽略/1允许dump fsck检查顺序0不检 # umount /E 不用时可以卸载

调整挂载点 /home的容量到根 /

df -h
# 发现/dev/mapper/centos-root 所剩空间很少,而 /dev/mapper/centos-home 有size 42G sudo tar zcf /run/home.tar.gz /home # 打包home到run下,因为run有足够的空间可以暂存 yum install -y psmisc # 安装fuser
sudo fuser -km /home # 结束 home相关进程 yum install -y lsof # 也可使用 lsof |grep /home/ 来查看占用home的进程,然后kill sudo umount /home # 卸载
sudo lvremove /dev/mapper/centos-home # 移除lv分区
sudo lvextend -L +30G /dev/mapper/centos-root # 增加root 30G
sudo xfs_growfs /dev/mapper/centos-root # 扩大文件系统 sudo lvcreate -L 11G -n/dev/mapper/centos-home # 只剩11G,都给home, 如果超过可用大小,会有提示。
sudo mkfs.xfs /dev/mapper/centos-home # 格式化
sudo mount /dev/mapper/centos-home # 挂载
sudo tar zxf /run/home.tar.gz -C / # 恢复home

挂载windows的共享:

mount -t cifs -ro username=admin,password= //192.168.1.12/share /opt/share
  • username,password 是windows登录用户名密码
  • //192.168.1.12/share 是windows的共享文件夹
  • /share是希望Centos7将要挂载到的地方,可任意位置

开机启动就挂载文件夹,在/etc/fstab文件中添加

//192.168.1.12/share /share cifs username=admin,password=123456   0 0

知识点参考:http://www.jinbuguo.com/man/mount.cifs.html

如果失败,可能缺少组件。 yum install cifs-utils

shell编程一定要注意,变量名和=之间不能有空格; 原生bash不支持简单数学运算,必须借助expr表达式工具等。

对于习惯其它开发语言的人来说,这个shell的格式很容易让人出错。

想要掌握并记忆,还是要多写几次练习。

#!/bin/bash 

# 上面第一行是解释器   bash shell是Linux默认的免费的
## 通常会在第二行开始写脚本说明,作者,时间等。 #chmod +x hello.sh # 给全部用户加上执行权限 脚本的执行需要有x权限
#chmod u+x hello.sh #给当前用户加上执行权限
chmod hello.sh # 所有者 所属组 其他人。 = ++ 表示拥有"读/写/执行"的权限 cat /etc/shells #查看当前系统中的所有shell ## 执行脚本时 -x 参数可以看到具体拭执行过程 ###################### shell 第一个例子:查看系统概况 ###################
# echo -e 参数可以识别字符串中的转义字符
#!/bin/sh
# auto mail for sys info
/bin/date +%F >> /tmp/sysinfo # 日期信息写入临时文件
echo "disk info:" >> /tmp/sysinfo
/bin/df -h >> /tmp/sysinfo # 真正的disk信息
echo >> /tmp/sysinfo # 显示空行
echo "online users:" >> /tmp/sysinfo
/usr/bin/who | /bin/grep -v root >> /tmp/sysinfo # 列出所有用户,不看root
echo >> /tmp/sysinfo
echo "memory info:" >> /tmp/sysinfo
/usr/bin/free -m >> /tmp/sysinfo
echo >> /tmp/sysinfo # write root
/usr/bin/write root < /tmp/sysinfo && /bin/rm /tmp/sysinfo #信息发给root,然后删除
# crontab -e
# * * - script ###################### end 第一个例子 ################################## ###################### 变量 ####################################
name="abcde" # 变量名和=之间不能有空格 export a='aaaaa' #声明为全局变量 # 在a.sh中调用b.sh 写上source则表示在同一个进程中执行.
source ./b.sh
. ./b.sh # 也可用. 来代替source echo "${name}s a bcd." # 大括号确定了变量的边界 注意需要使用双引号;单引号则不会识别变量 readonly aa= # 只读变量aa,不可修改 unset a ## 删除变量 ##局部变量仅能在当前会话中访问.
set ##set命令可以查看环境变量 ###################### 变量参数 ####################################
#脚本内获取参数的格式为$n n代表数字, 1第一个参数,2是第二个参数,以此类推...
#特殊符号:
$#参数个数,
$*所有参数为一个字符串,
$$脚本运行的当前进程ID,
$!后台运行的最后一个进程ID,
$@ 与$*相同,但是使用时加引号,在引号中返回每个参数.
$? 显示最后命令状态,
$*与$@区别: 是否被双引号包含. #!/bin/bash
echo "脚本名称: $0";
echo "第一个参数: $1";
echo "参数个数: $#";
echo "传递的参数作为一个字符串: $*";
echo "进程号: $$";
echo "结束: $?"; ###################### 第二个例子: 备份 ##################################
# $ 利用了位置参数. 例如执行 sh autobak.sh /usr 时,$ 即表示/usr #!/bin/bash
# backup files by date DATE=`/bin/date +%Y%m%d`
/bin/tar -cf /backup/$.$DATE.tar $ > /dev/null >> /backup/$.bak.log
/bin/gzip /backup/$.$DATE.tar
if [ $? -eq ]
then
echo "$1 $DATE backup successful" >> /backup/$.bak.log
else
echo "ERROR: failure $1 $DATE backup!" >> /backup/$.bak.log
fi
# crontab -e
# * * , script ###################### 第二个例子: 备份 ################################## ################################ shell 运算符##############################
# 原生bash不支持简单数学运算,可借助expr表达式工具以及``符号 ,完成求值.
# 其实``叫命令替换符
val=`expr +` #输出2+
val=`expr + ` #输出5
val=`expr \* ` #输出6 乘法要转义
val=`expr / ` #除法
val=`expr % ` #取模
#也可以用$(())或$[] 进行算术运算
#!/bin/bash
count=
((count++))
echo $count
a=$((+))
b=$[+]
echo $a $b # 关系运算符 简称: -eq等于, -nq不等于, -gt大于, -lt小于, -ge大于等于, -le小于等于
# 关系运算符只支持数据,不支持字符串,除非是数字形字符串
#!/bin/bash
a=
b=
if [ $a -eq $b ]
then
echo "$a -eq $b : a等于b"
else
echo "$a -nq $b : a不等于b"
fi if [ -lt ]; then echo OK; else echo notok; fi ##单行写法. # 布尔运算符 -a且 -o或 只需单层方括号
if [ $a -lt -a $b -gt ]
then
echo "$a 小于100且 $b 大于15 : 返回true"
else
echo "$a 不小于100或 $b 不大于15 : 返回false"
fi # 逻辑运算符 && 及|| 需要双层方括号
if [[ $a -lt || $b -gt ]]
then
echo "返回true"
else
echo "返回false"
fi # 字符串运算符
#!/bin/bash
a=""
b="abc"
if [ -z $a ] # 字符串长度为0返回true
then
echo "长度0"
else
echo "长度非0"
fi
if [ -n $b ] # 字符串长度不为0返回true 和-z相反
then
echo "长度不为0"
else
echo "长度为0"
fi
## if [ $a ] #字符串是否存在 # 文件测试运算符
#!/bin/bash
file="/test/1.sh"
if [ -r $file ] # -r 可读, -w 可写, -x 可执行, -d 是否目录 -f是否文件 -e是否存在
then
echo "文件可读"
else
echo "文件不可读"
fi ############################# 流程控制 ###################################
# 单if语句可以写成一行, 用;隔开,但也必须有fi结尾
if [ $(ps -ef | grep -c "ssh") -gt ]; then echo "true"; fi # 查找当前系统中有多少个ssh进程
# 中间如果有多个判断用 elif ## read 用于从控制台读取输入.
#!/bin/bash
read -p "please input your name: " NAME
if [ $NAME = root ]
then
echo "hello ${NAME}, welcome!"
elif [ $NAME = itcast ]
then
echo "hello ${NAME}, Wlcm"
else
echo "SB, get out here."
fi
#### 注意空格不能少. ######## for循环,有几种写法
for N in ; do echo $N; done #一句写完,循环3次
for N in {..}; do echo $N; done #一句写完,循环5次
for((i=;i<=;i++));do echo "welcome $i times"; done #和其它语言相近的写法.
#或者:
for((i=;i<=;i++))
do
echo "welcome $i times"
done ####### while
#!/bin/bash
i=
while((i<=))
do
echo $i
let i++ # let是bash中用于计算的工具,变量计算中不需加$
done
####### case
#!/bin/bash
echo '输入1到4之间的数字:'
read aNum
case $aNum in
) echo '你选择了1'
;;
) echo '你选择了2'
;;
) echo '你选择了3'
;;
) echo '你选择了4'
;;
*) echo '你没有输入1到4之间的数'
;;
esac #注意分支的半括号和双分号. ############################# 函数 ##########################################
#函数必须在使用前定义, 函数名前面可以省略function.
#参数返回,可加return,如果不加,会将最后一条命令的结果作为返回值. return后跟数值(-)
#调用时直接写函数名即可.
#!/bin/bash
#fun2.sh
funWithReturn(){
echo "此函数会对输入的两个数进行相加运算..."
echo "输入第一个数:"
read aNum
echo "输入第二个数:"
read bNum
echo "两个数分别为 $aNum 和$bNum "
return $(($aNum + $bNum))
}
#funWithReturn
#echo "两数之和为: $?" #!/bin/bash
#caller.sh
. /test/fun2.sh #跨脚本调用函数
funWithReturn ####### 函数传参
#!/bin/bash
funWithParam(){
echo "第一个参数为 $1 "
echo "第二个参数为 $2 "
a=$
b=$
echo $(($a + $b))
echo "第10个参数为 $10 "
echo "第十个参数为 ${10} "
echo "第十一个参数为 ${11} "
echo "参数总共有 $# "
echo "作为一个字符串输出所有参数 $* "
}
funWithParam

模拟上传log文件到HDFS的shell示例:

假设logs/log/ 下的access.log文件是正在采集中的日志. 而后面带有数字的 access.log.1 文件是前一天的日志文件.

这个shell要做的是将前一天的日志都上传到hdfs上去. 如果结合crontab 就可以实现定时上传.

upload2hdfs.sh 文件:

#!/bin/bash

#set java env
export JAVA_HOME=/usr/local/src/jdk1..0_161
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
#set hadoop env
export HADOOP_HOME=/usr/local/src/hadoop-2.7.
export PATH=${HADOOP_HOME}/bin:${HADOOP_HOME}/sbin:$PATH #日志文件存放的目录
log_src_dir=/root/logs/log/ #待上传文件存放的目录
log_toupload_dir=/root/logs/toupload/ #日志文件上传到hdfs的根路径
date1=`date -d last-day +%Y_%m_%d`
hdfs_root_dir=/data/clickLog/$date1/ #打印环境变量信息
echo "envs: hadoop_home: $HADOOP_HOME" #读取日志文件的目录,判断是否有需要上传的文件
echo "log_src_dir:" $log_src_dir
ls $log_src_dir | while read fileName
do
if [[ "$fileName" == access.log.* ]]; then
date=`date +%Y_%m_%d_%H_%M_%S`
#将文件移动到待上传目录并重命名
#打印信息
echo "moving $log_src_dir$fileName to $log_toupload_dir"xxxxx_click_log_$fileName"$date"
mv $log_src_dir$fileName $log_toupload_dir"xxxxx_click_log_$fileName"$date
#将待上传的文件path写入一个列表文件willDoing
echo $log_toupload_dir"xxxxx_click_log_$fileName"$date >> $log_toupload_dir"willDoing."$date
fi
done
#找到列表文件willDoing ## grep -v是不包含
ls $log_toupload_dir | grep will | grep -v "_COPY_" | grep -v "_DONE_" | while read line
do
#打印信息
echo "toupload is in file:"$line
#将待上传文件列表willDoing改名为winllDoing_COPY_
mv $log_toupload_dir$line $log_toupload_dir$line"_COPY_"
#读列表文件willDoing_COPY_的内容(一个一个的待上传文件名), 此处的line就是列表中的一个待上传文件的path
cat $log_toupload_dir$line"_COPY_" | while read line
do
#打印信息
echo "puting... $line to hdfs path... $hdfs_root_dir"
hdfs dfs -mkdir -p $hdfs_root_dir
hdfs dfs -put $line $hdfs_root_dir
done
mv $log_toupload_dir$line"_COPY_" $log_toupload_dir$line"_DONE_"
done

假设hdfs在正常运行, 本地执行:

cd /root
mkdir -p logs/log vim upload2hdfs.sh
# 将代码贴上, 检查各路径是否正确. 保存退出. chmod ./upload2hdfs.sh # 给予执行权限. ./upload2hdfs.sh #等待成功执行完成后, 检查hdfs上是否有刚上传的文件.

实际案例:logstate.sh脚本 结合 crontab 定时重开日志文件:

#!/bin/bash
#Rotate the MongoDB logs to prevent a single logfile from consuming too much disk space.
app=mongod
mongodPath=/data/mongo4.2.0/bin
pidArray=$(/usr/sbin/pidof $mongodPath/$app)
for pid in $pidArray;do
if [ $pid ]
then
kill -SIGUSR1 $pid
fi
done

如果没有root权限,而crontab执行的命令中又需要sudo 则可以:

sudo crontab -u root -e
sudo crontab -u root -l

注意:crond进程如果多个,会造成crontab被执行多次的情况。

sudo 碰到重定向 > 时,权限不足。可以使用 sh -c :

sudo sh -c "echo a > 1.txt"