博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux shell的一些小结
阅读量:4079 次
发布时间:2019-05-25

本文共 2030 字,大约阅读时间需要 6 分钟。

最近在做大数据分析的项目,需要编写shell脚本。之前写shell脚本的次数比较少,处于一种了解的状态。但是经过这个月反复修改编写shell脚本下来,对shell也算是入门了吧。所以特意把自己的一些觉得好的习惯写下来,也方便以后复制(* ̄︶ ̄)。


脚本与目录分离

有这种想法是因为,写完shell之后需要部署生成环境的集群。在本地集群是在用户目录下开发,但是生成环境下的部署目录又是另外一个用户目录,这就造成了部署时总是需要修改目录,移植性差,不胜其烦。

鉴于这种原因,我想了个“笨办法”,在脚本中用pwd命令获取到当前的路径。

now_path=`pwd`echo ${now_path}

实际上这个获取的不是脚本所在的目录,假设在根目录下输入绝对路径执行,那么pwd获取的就是根目录了!为了保险起见,通常会在前面加上一个

cd '/path'

就相当设置了一个全局变量,其实还是没有实现脚本于路径的分离。

正确的做法:

CURR_DIR=$(cd `dirname $0`; pwd)echo ${CURR_DIR}

这样无论是在哪里执行脚本,获取的都是脚本所在路径。因为$0参数是脚本名称。dirname可以去除文件名的非目录部分,得到的就是“.”,也就是current_directory。所以再cd,pwd就可以获取脚本所在的路径了。

脚本的错误日志

刚开始因为考虑到脚本的可阅读行和程序排查问题方便,会在脚本中重定向一些 文字到固定的目录文件中。但是几次都发现错误信息是不会重定向到我所在的文件的。日志中只有我print出来的内容。

1、单纯使用的是后台命令运行的情况

./script.sh &

有错误发生会显示在终端上,普通的INFO信息则会输出到我设置的固定的日志文件中。如果终端关闭了,那错误就无从查其。

2、使用nohup重定向+后台运行的情况

nohup ./script.sh &

这样执行就会把错误日志输出到nohup.out文件中了,可以解决错误日志丢失的问题。但是如果一个脚本经常重复执行,只有一个nohup.out文件是比较难查找问题的(因为我的INFO信息日志都是按脚本名,按日期分文件打印的)。

3、shell的标准输出、入和错误输出

一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件():

  • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
  • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息

    我想要的错误日志其实就是shell的错误输出流,知道了这个就方便了。在我的实际中,业务都是需要不同脚本的配置才能实现的,因此,在总脚本中执行其他分脚本并把分脚本的错误输出和标准输出都重定向到总脚本的日志中就好了

startAll.sh

#!/bin/shCURR_DIR=$(cd `dirname $0`; pwd)today=$(date +'%Y%m%d')LOG_FILE=${now_path}/logs/${0}_${today}.txtmkdir -p ${now_path}/logstouch ${log_file}#---echo 'start first script'>>${LOG_FILE}./first.sh >>${LOG_FILE} 2>$1echo 'start second script'>>${LOG_FILE}./second.sh >>${LOG_FILE} 2>$1echo 'all script had finished.'>>${LOG_FILE}

这样就能把错误和信息日志输出到日志文件中了。

提供脚本运行说明

一开始我是把脚本的运行说明写成注释放到脚本中的,但是后来由于业务需要,脚本需要加密,所以,为了方便,需要把说明写在脚本中。这里的是参考了INFOQ公众号的一篇文章(文章链接可能失效)。里面讲的技巧中,有些技巧感觉有些没有太大的必要使用。它提供的–help技巧代码中有点小错误。改进后变成了下面的样子:

if [ ${#@} -eq 1 ] && [ "${@#"--help"}" = "" ]; thenprintf -- '====== Help ======\n';printf -- '|运行说明:\n';printf -- '|第一个参数输入4G数据源表名(没有经过删减字段版的),第二个参数输入时间(yyyymmdd)\n';printf -- '|示例: ./flow_first_step.sh t_mult_s1u_http_p 20180606\n'exit 0;fi;

当然,把运行说明写成usage函数也是可以的。


转载地址:http://ntsni.baihongyu.com/

你可能感兴趣的文章
zookeeper单机集群安装
查看>>
do_generic_file_read()函数
查看>>
Python学习笔记之数据类型
查看>>
Python学习笔记之特点
查看>>
shell 快捷键
查看>>
VIM滚屏操作
查看>>
EMC 2014存储布局及十大新技术要点
查看>>
linux内核内存管理(zone_dma zone_normal zone_highmem)
查看>>
将file文件内容转成字符串
查看>>
循环队列---数据结构和算法
查看>>
优先级队列-数据结构和算法
查看>>
链接点--数据结构和算法
查看>>
servlet中请求转发(forword)与重定向(sendredirect)的区别
查看>>
Spring4的IoC和DI的区别
查看>>
springcloud 的eureka服务注册demo
查看>>
eureka-client.properties文件配置
查看>>
MODULE_DEVICE_TABLE的理解
查看>>
platform_device与platform_driver
查看>>
platform_driver平台驱动注册和注销过程(下)
查看>>
.net强制退出主窗口的方法——Application.Exit()方法和Environment.Exit(0)方法
查看>>