- 浏览: 2653499 次
- 来自: 杭州
文章分类
- 全部博客 (1188)
- webwork (4)
- 网摘 (18)
- java (103)
- hibernate (1)
- Linux (85)
- 职业发展 (1)
- activeMQ (2)
- netty (14)
- svn (1)
- webx3 (12)
- mysql (81)
- css (1)
- HTML (6)
- apache (3)
- 测试 (2)
- javascript (1)
- 储存 (1)
- jvm (5)
- code (13)
- 多线程 (12)
- Spring (18)
- webxs (2)
- python (119)
- duitang (0)
- mongo (3)
- nosql (4)
- tomcat (4)
- memcached (20)
- 算法 (28)
- django (28)
- shell (1)
- 工作总结 (5)
- solr (42)
- beansdb (6)
- nginx (3)
- 性能 (30)
- 数据推荐 (1)
- maven (8)
- tonado (1)
- uwsgi (5)
- hessian (4)
- ibatis (3)
- Security (2)
- HTPP (1)
- gevent (6)
- 读书笔记 (1)
- Maxent (2)
- mogo (0)
- thread (3)
- 架构 (5)
- NIO (5)
- 正则 (1)
- lucene (5)
- feed (4)
- redis (17)
- TCP (6)
- test (0)
- python,code (1)
- PIL (3)
- guava (2)
- jython (4)
- httpclient (2)
- cache (3)
- signal (1)
- dubbo (7)
- HTTP (4)
- json (3)
- java socket (1)
- io (2)
- socket (22)
- hash (2)
- Cassandra (1)
- 分布式文件系统 (5)
- Dynamo (2)
- gc (8)
- scp (1)
- rsync (1)
- mecached (0)
- mongoDB (29)
- Thrift (1)
- scribe (2)
- 服务化 (3)
- 问题 (83)
- mat (1)
- classloader (2)
- javaBean (1)
- 文档集合 (27)
- 消息队列 (3)
- nginx,文档集合 (1)
- dboss (12)
- libevent (1)
- 读书 (0)
- 数学 (3)
- 流程 (0)
- HBase (34)
- 自动化测试 (1)
- ubuntu (2)
- 并发 (1)
- sping (1)
- 图形 (1)
- freemarker (1)
- jdbc (3)
- dbcp (0)
- sharding (1)
- 性能测试 (1)
- 设计模式 (2)
- unicode (1)
- OceanBase (3)
- jmagick (1)
- gunicorn (1)
- url (1)
- form (1)
- 安全 (2)
- nlp (8)
- libmemcached (1)
- 规则引擎 (1)
- awk (2)
- 服务器 (1)
- snmpd (1)
- btrace (1)
- 代码 (1)
- cygwin (1)
- mahout (3)
- 电子书 (1)
- 机器学习 (5)
- 数据挖掘 (1)
- nltk (6)
- pool (1)
- log4j (2)
- 总结 (11)
- c++ (1)
- java源代码 (1)
- ocr (1)
- 基础算法 (3)
- SA (1)
- 笔记 (1)
- ml (4)
- zokeeper (0)
- jms (1)
- zookeeper (5)
- zkclient (1)
- hadoop (13)
- mq (2)
- git (9)
- 问题,io (1)
- storm (11)
- zk (1)
- 性能优化 (2)
- example (1)
- tmux (1)
- 环境 (2)
- kyro (1)
- 日志系统 (3)
- hdfs (2)
- python_socket (2)
- date (2)
- elasticsearch (1)
- jetty (1)
- 树 (1)
- 汽车 (1)
- mdrill (1)
- 车 (1)
- 日志 (1)
- web (1)
- 编译原理 (1)
- 信息检索 (1)
- 性能,linux (1)
- spam (1)
- 序列化 (1)
- fabric (2)
- guice (1)
- disruptor (1)
- executor (1)
- logback (2)
- 开源 (1)
- 设计 (1)
- 监控 (3)
- english (1)
- 问题记录 (1)
- Bitmap (1)
- 云计算 (1)
- 问题排查 (1)
- highchat (1)
- mac (3)
- docker (1)
- jdk (1)
- 表达式 (1)
- 网络 (1)
- 时间管理 (1)
- 时间序列 (1)
- OLAP (1)
- Big Table (0)
- sql (1)
- kafka (1)
- md5 (1)
- springboot (1)
- spring security (1)
- Spring Boot (3)
- mybatis (1)
- java8 (1)
- 分布式事务 (1)
- 限流 (1)
- Shadowsocks (0)
- 2018 (1)
- 服务治理 (1)
- 设计原则 (1)
- log (0)
- perftools (1)
最新评论
-
siphlina:
课程——基于Python数据分析与机器学习案例实战教程分享网盘 ...
Python机器学习库 -
san_yun:
leibnitz 写道hi,我想知道,无论在92还是94版本, ...
hbase的行锁与多版本并发控制(MVCC) -
leibnitz:
hi,我想知道,无论在92还是94版本,更新时(如Puts)都 ...
hbase的行锁与多版本并发控制(MVCC) -
107x:
不错,谢谢!
Latent Semantic Analysis(LSA/ LSI)算法简介 -
107x:
不错,谢谢!
Python机器学习库
许多人用shell脚本完成一些简单任务,而且变成了他们生命的一部分。不幸的是,shell脚本在运行异常时会受到非常大的影响。在写脚本时将这类问题最小化是十分必要的。本文中我将介绍一些让bash脚本变得健壮的技术。
使用set -u
你因为没有对变量初始化而使脚本崩溃过多少次?对于我来说,很多次。
chroot=$1 ... rm -rf $chroot/usr/share/doc
如果上面的代码你没有给参数就运行,你不会仅仅删除掉chroot中的文档,而是将系统的所有文档都删除。那你应该做些什么呢?好在bash提供了set -u ,当你使用未初始化的变量时,让bash自动退出。你也可以使用可读性更强一点的set -o nounset 。
david% bash /tmp/shrink-chroot.sh
$chroot=
david% bash -u /tmp/shrink-chroot.sh
/tmp/shrink-chroot.sh: line 3: $1: unbound variable
david%
使用set -e
你写的每一个脚本的开始都应该包含set -e 。这告诉bash一但有任何一个语句返回非真的值,则退出bash。使用-e的好处是避免错误滚雪球般的变成严重错误,能尽早的捕获错误。更加可读的版本:set -o errexit
使用-e把你从检查错误中解放出来。如果你忘记了检查,bash会替你做这件事。不过你也没有办法使用$? 来获取命令执行状态了,因为bash无法获得任何非0的返回值。你可以使用另一种结构:
command
if [ "$?"-ne 0]; then echo "command failed"; exit 1; fi
可以替换成:
command || { echo "command failed"; exit 1; }
或者使用:
if ! command; then echo "command failed"; exit 1; fi
如果你必须使用返回非0值的命令,或者你对返回值并不感兴趣呢?你可以使用 command || true ,或者你有一段很长的代码,你可以暂时关闭错误检查功能,不过我建议你谨慎使用。
set +e
command1
command2
set -e
相关文档指出,bash默认返回管道中最后一个命令的值,也许是你不想要的那个。比如执行 false | true 将会被认为命令成功执行。如果你想让这样的命令被认为是执行失败,可以使用 set -o pipefail
程序防御 - 考虑意料之外的事
你的脚本也许会被放到“意外”的账户下运行,像缺少文件或者目录没有被创建等情况。你可以做一些预防这些错误事情。比如,当你创建一个目录后,如果父目录不存在,mkdir 命令会返回一个错误。如果你创建目录时给mkdir 命令加上-p选项,它会在创建需要的目录前,把需要的父目录创建出来。另一个例子是 rm 命令。如果你要删除一个不存在的文件,它会“吐槽”并且你的脚本会停止工作。(因为你使用了-e选项,对吧?)你可以使用-f选项来解决这个问题,在文件不存在的时候让脚本继续工作。
准备好处理文件名中的空格
有些人从在文件名或者命令行参数中使用空格,你需要在编写脚本时时刻记得这件事。你需要时刻记得用引号包围变量。
if [ $filename = "foo" ];
当$filename 变量包含空格时就会挂掉。可以这样解决:
if [ "$filename" = "foo" ];
使用$@ 变量时,你也需要使用引号,因为空格隔开的两个参数会被解释成两个独立的部分。
david% foo() { for i in $@; do echo $i; done }; foo bar "baz quux"
bar
baz
quux
david% foo() { for i in "$@"; do echo $i; done }; foo bar "baz quux"
bar
baz quux
我没有想到任何不能使用"$@" 的时候,所以当你有疑问的时候,使用引号就没有错误。
如果你同时使用find和xargs,你应该使用 -print0 来让字符分割文件名,而不是换行符分割。
david% touch "foo bar"
david% find | xargs ls
ls: ./foo: No such file or directory
ls: bar: No such file or directory
david% find -print0 | xargs -0 ls
./foo bar
设置的陷阱
当你编写的脚本挂掉后,文件系统处于未知状态。比如锁文件状态、临时文件状态或者更新了一个文件后在更新下一个文件前挂掉。如果你能解决这些问题,无论是 删除锁文件,又或者在脚本遇到问题时回滚到已知状态,你都是非常棒的。幸运的是,bash提供了一种方法,当bash接收到一个UNIX信号时,运行一个 命令或者一个函数。可以使用trap 命令。
trap command signal [signal ...]
你可以链接多个信号(列表可以使用kill -l获得),但是为了清理残局,我们只使用其中的三个:INT ,TERM 和EXIT 。你可以使用-as来让traps恢复到初始状态。
信号描述
INT |
Interrupt - 当有人使用Ctrl-C终止脚本时被触发 |
TERM |
Terminate - 当有人使用kill杀死脚本进程时被触发 |
EXIT |
Exit - 这是一个伪信号,当脚本正常退出或者set -e后因为出错而退出时被触发 |
当你使用锁文件时,可以这样写:
if [ ! -e $lockfile ]; then
touch $lockfile
critical-section
rm $lockfile
else
echo "critical-section is already running"
fi
当最重要的部分(critical-section)正在运行时,如果杀死了脚本进程,会发生什么呢?锁文件会被扔在那,而且你的脚本在它被删除以前再也不会运行了。解决方法:
if [ ! -e $lockfile ]; then
trap " rm -f $lockfile; exit" INT TERM EXIT
touch $lockfile
critical-section
rm $lockfile
trap - INT TERM EXIT
else
echo "critical-section is already running"
fi
现在当你杀死进程时,锁文件一同被删除。注意在trap命令中明确地退出了脚本,否则脚本会继续执行trap后面的命令。
竟态条件 (wikipedia )
在上面锁文件的例子中,有一个竟态条件是不得不指出的,它存在于判断锁文件和创建锁文件之间。一个可行的解决方法是使用IO重定向和bash的noclobber(wikipedia )模式,重定向到不存在的文件。我们可以这么做:
if ( set -o noclobber; echo "$$" > "$lockfile") 2> /dev/null;
then
trap 'rm -f "$lockfile"; exit $?' INT TERM EXIT
critical-section
rm -f "$lockfile"
trap - INT TERM EXIT
else
echo "Failed to acquire lockfile: $lockfile"
echo "held by $(cat $lockfile)"
fi
更复杂一点儿的问题是你要更新一大堆文件,当它们更新过程中出现问题时,你是否能让脚本挂得更加优雅一些。你想确认那些正确更新了,哪些根本没有变化。比如你需要一个添加用户的脚本。
add_to_passwd $user
cp -a /etc/skel /home/$user
chown $user /home/$user -R
当磁盘空间不足或者进程中途被杀死,这个脚本就会出现问题。在这种情况下,你也许希望用户账户不存在,而且他的文件也应该被删除。
rollback() {
del_from_passwd $user
if [ -e /home/$user ]; then
rm -rf /home/$user
fi
exit
}
trap rollback INT TERM EXIT
add_to_passwd $user
cp -a /etc/skel /home/$user
chown $user /home/$user -R
trap - INT TERM EXIT
在脚本最后需要使用trap关闭rollback调用,否则当脚本正常退出的时候rollback将会被调用,那么脚本等于什么都没做。
保持原子化
又是你需要一次更新目录中的一大堆文件,比如你需要将URL重写到另一个网站的域名。你也许会写:
for file in $(find /var/www -type f -name "*.html"); do
perl -pi -e 's/www.example.net/www.example.com/' $file
done
如果修改到一半是脚本出现问题,一部分使用www.example.com,而另一部分使用www.example.net。你可以使用备份和trap解决,但在升级过程中你的网站URL是不一致的。
解决方法是将这个改变做成一个原子操作。先对数据做一个副本,在副本中更新URL,再用副本替换掉现在工作的版本。你需要确认副本和工作版本目录在同一个磁盘分区上,这样你就可以利用Linux系统的优势,它移动目录仅仅是更新目录指向的inode节点。
cp -a /var/www /var/www-tmp
for file in $(find /var/www-tmp -type -f -name "*.html"); do
perl -pi -e 's/www.example.net/www.example.com/' $file
done
mv /var/www /var/www-old
mv /var/www-tmp /var/www
这意味着如果更新过程出问题,线上系统不会受影响。线上系统受影响的时间降低为两次mv操作的时间,这个时间非常短,因为文件系统仅更新inode而不用真正的复制所有的数据。
这种技术的缺点是你需要两倍的磁盘空间,而且那些长时间打开文件的进程需要比较长的时间才能升级到新文件版本,建议更新完成后重新启动这些进程。对于 apache服务器来说这不是问题,因为它每次都重新打开文件。你可以使用lsof命令查看当前正打开的文件。优势是你有了一个先前的备份,当你需要还原 时,它就派上用场了。
进阶阅读
发表评论
-
使用dig查询dns解析
2016-12-01 10:39 1401一般来说linux下查询域名解析有两种选择,nslookup ... -
Linux监控工具-Nmon命令行:Linux系统性能的监测利器
2014-09-01 10:49 1834Nmon是一款面向系统管理员的调优和基准测量工具,可以用来显 ... -
安装MySQL-python问题解决
2014-08-20 12:29 14046今天在centos安装MySQL-python,结果报错, ... -
curl POST提交
2014-08-19 16:59 1038curl POST提交的例子: curl "l ... -
通过sar查看网卡流量
2014-08-13 17:30 1523这个工具RHEL5自带有,默认也安装。 一个强大的工具(好 ... -
解决thinkpad t440p ubuntu 14.04无线不能用问题
2014-07-09 22:23 1131前段时间新入手了一台thinkpad t440p,一直来都 ... -
故障排除的第一个五分钟
2014-04-15 14:05 1332原文:http://junqili.com/linux/tr ... -
Linux 性能监测总结
2014-04-14 15:22 835Linux 性能监测:介绍Linux 性能监测:MemoryL ... -
linux free 命令解释
2014-03-22 10:28 1215linux系统内存实际 ... -
超简单方法创建Ubuntu系统可启动U盘
2014-03-11 17:23 2986现在做系统,最方便的方法还是要属U盘启动,随身携带,插入电脑 ... -
Linux 2.6.36内核优化指南
2013-12-26 16:03 1151作者:Ken Wu Email: ken.wug@gmai ... -
Linux下终端利器tmux
2013-11-28 12:01 8736原文:http://kumu-linux.gi ... -
理解inode
2013-11-18 15:18 728文章某位附带一个利用inode监控日志被覆盖的python脚 ... -
Linux 性能测试与分析
2013-11-11 16:31 2057本文参考:http://testing. ... -
Iowait的成因、对系统影响及对策
2013-11-11 16:07 1666参考: Iowait的成因、对系统影响及对策 -
linux运行时提示找不到某个so
2013-11-10 15:22 2912有时候通过linux编译安装一些程序会有类似这样的错误提示: ... -
shell入门
2013-09-11 16:04 865变量赋值 shell中变量赋值不能有空格,比如必须 a= ... -
基于tmpfs或ramfs把linux把目录映射为内存
2013-08-28 13:24 5847在linux系统中,我们可以通过挂载tmpfs或ramfs ... -
Linux查看新磁盘
2013-08-26 16:34 1238通过fdisk -l [admin@server9 jyp ... -
linux 系统环境设置
2013-04-03 18:04 1121yum--update 服务停止 /sbin/se ...
相关推荐
以下是一些提高Bash脚本健壮性的关键技巧: 1. **使用`set -u`**: `set -u` 或 `set -o nounset` 是Bash的一个选项,它强制脚本在使用未定义的变量时立即退出。这有助于避免因未初始化的变量导致的潜在危险,例如...
### Linux中高效编写Bash脚本的9个技巧 ...总之,以上这些技巧可以帮助开发者编写出更加高效、可靠和易于维护的Bash脚本。无论是初学者还是经验丰富的系统管理员,掌握这些基础知识都是非常有益的。
通过阅读《高级Bash脚本编程指南》,你可以深入理解Bash脚本的内在原理,并能够编写出高效、可靠的自动化脚本来简化日常的Linux系统管理工作。书中实例丰富,注释详细,非常适合自学和参考。同时,配合HTML格式的...
最后,本书可能还会讨论bash的调试技巧和最佳实践,帮助开发者定位问题并写出更健壮的脚本。例如,使用set命令启用脚本的调试模式,或者通过set -o nounset防止未定义变量的使用,可以避免很多潜在的错误。 总的来...
在IT行业中,Shell脚本是一种极其实用的工具,特别是在系统管理、自动化任务执行以及日常工作效率提升方面。...不过,通过学习和应用这些Bash脚本的基础知识,你可以创建出适应各种业务需求的自动化工具。
错误处理和调试技巧,帮助你写出更健壮的脚本;以及如何利用脚本与系统交互,如处理进程、系统资源和网络通信。对于那些希望深入理解Linux系统工作原理和提升系统管理技能的人来说,这部分内容尤为重要。 通过阅读...
这份“高级Bash编程”教程,尽管年代稍显久远,但其内容仍然具有很高的实用价值,尤其对于那些希望通过掌握Bash脚本提高工作效率或进行自动化任务处理的人来说,是一份不可或缺的学习资料。 一、Bash基础 1. **...
5. **错误处理**:使用`set -e`来使脚本在遇到错误时立即退出,确保脚本的健壮性。 通过深入学习和实践这些概念,你将能够编写出高效、灵活的Bash脚本来自动化日常任务,提高工作效率。在实际应用中,不断探索Bash...
文档列出了Shell脚本中的常用命令,例如grep、nohup、tar、unzip和cp等,这些命令是Shell脚本编写中常用的工具。grep命令用于在文件中搜索特定的文本模式,并可以进行复杂的文本匹配操作,比如忽略大小写或显示匹配...
- **O¶**:这里可能介绍了一些最佳实践,帮助用户写出可维护性和可读性更好的脚本。 - **€²**:这部分可能探讨了如何处理脚本中的异常情况,确保脚本即使在出现问题时也能优雅地退出。 - **?§º‚**:这里可能...
BashSample项目是针对初学者设计的基础练习,旨在帮助用户熟悉Bash脚本编写和命令行操作。 1. **Bash基础概念** - **Shell**:Shell是操作系统提供的一种用户界面,允许用户与内核进行交互。 - **Bash Shell**:...
通过这种方式,可以创建出更健壮、可维护的自动化解决方案,尤其适用于那些需要复杂数据处理和逻辑判断的场景。 在实际项目中,我们可能还需要考虑错误处理、日志记录、性能优化等细节。例如,使用try-except捕获...
2. 脚本文件:如`script1.py`、`script2.sh`等,分别代表Python脚本和Bash脚本。 3. 测试文件:用于验证脚本功能的正确性,如`test_script1.py`。 4. 配置文件:可能包含环境变量、数据库连接信息等,如`.env`。 5. ...
2. **提升脚本健壮性**:对脚本中的变量进行更严格的校验,比如检查`ORACLE_SID`和`db_unique_name`等变量的有效性。 3. **优化性能**:对于非常大的日志文件,可以考虑采用更高效的读写策略,比如使用`dd`命令替代`...
要定义一个Bash函数,首先需要在shell会话或脚本中写一个函数名,后跟一对圆括号,里面包含执行的命令。例如,创建一个名为`greet`的函数,它打印一条问候消息: ```bash greet() { echo "Hello, World!" } ``...
这不仅能帮助我们写出健壮的脚本,还能提升代码的可读性和维护性。 总的来说,"LINUX与UNIX SHELL编程指南"将引导读者全面理解Shell编程,通过学习,你可以编写出自动化任务、管理文件系统、集成系统服务,甚至构建...
- **陷阱和常见错误**:它能识别出可能导致问题的常见模式,如不安全的文件操作、未捕获的错误条件等,帮助你写出更健壮的脚本。 要在Windows上运行Shellcheck,首先解压文件,然后双击`shellcheck-latest.exe`。你...