以Korn Shell为例分享脚本开发中的常见问题

避免定时任务脚本的">常见问题

很多脚本在实际使用的时候往往是以定时任务的方式运行,而非手工运行。但是实现同样功能的脚本在这两种运行方式下可能遇到的问题不尽相同。

以定时任务方式运行的脚本往往会遇到以下几个问题。

路径问题:当前目录往往不是脚本文件所在目录。因此,脚本在引用其使用的外部文件,如配置文件和其它脚本文件时,无法方便得使用相对路径。 命令找不到问题:脚本中使用到的一些外部命令,在手工执行脚本的时候可以正常调用。但是在定时任务下运行则可能出现脚本解析器找不到相关命令的问题。 脚本重复运行问题:一次脚本的执行未结束,而下一次脚本的运行已经开始。导致系统中有多个进程在同时运行
同一个脚本。

下面分享定时任务脚本开发中上述几个常见问题的处理方法。

路径问题

定时任务下当前路径往往不是脚本文件所在目录。因此我们需要用绝对路径来引用。即先获取脚本所在目录,然后以该目录为基础采用绝对路径的方式去引用脚本所需的外部文件。方法如下面代码所示。

清单 1. 获取脚本文件所在路径

#!/usr/bin/kshecho "Current path is: `pwd`"scriptPath=`dirname $0` #获取脚本所在路径echo "The script is located at: $scriptPath"cat "$scriptPath/readme" #使用绝对路径引用外部文件

将清单 1 中的脚本置于目录/opt/demo/scripts/auto-task 下,并在 cron 中添加该脚本。定时任务运行输出如下。

Current path is: /home/viscent

The script is located at: /opt/demo/scripts/auto-task

命令找不到问题

定时任务下运行的脚本可能出现脚本解析器找不到相关命令的问题。比如 Oracle 数据库中的 sqlplus 命令,脚本在调用该命令时若没有特殊处理则在定时任务下执行会使脚本解析器无法找到这个命令,出现如下所示的错误提示:

sqlplus: command not found

这是因为脚本在定时任务下执行时脚本是由非登录式 Shell 来执行的,并且执行脚本的父 Shell 并非 Oracle 用户的 Shell。因此,此时 Oracle 用户的.profile 文件并没有被调用。故解决的方法是在脚本的开头添加以下代码:

清单 2. 解决找不到外部命令问题

source /home/oracle/.profile

也就说,对于外部命令找不到的问题,可以通过在脚本的开头加一个 source 用户的.profile 文件的语句来解决。

脚本重复运行问题

定时任务脚本的另外一个常见问题是脚本重复运行的问题。比如,一个脚本被设置为每 5 分钟运行一次。若某一次该脚本的运行无法在 5 分钟内结束的话,定时任务服务仍然会新启一个进程来执行该脚本。这时就出现了运行同一个脚本的多个进程。而这可能导致脚本功能紊乱。并且浪费了系统资源。 避免脚本重复运行的方法通常有两种。一是在脚本执行时先检查系统是否存在运行该脚本的其它进程。若存在,则终止当前脚本的运行。二是,脚本运行时检查系统中是否存在其它进程运行该脚本。若存在,则结束那个进程(此方法有一定风险,慎用!)。这两种方法均需要在脚本的开头检查系统是否已经存在运行当前脚本的进程,若存在这样的进程则获取该进程的 PID。示例代码如下清单 3 所示。

清单 3. 防止脚本重复运行方法 1

#!/usr/bin/kshmain(){selfPID="$$"scriptFile="$0"typeset existingPidexistingPid=`getExistingPIDs $selfPID "$scriptFile"`if [ ! -z "$existingPid" ]; then echo "The script already running, exiting..." exit -1fidoItsTask}#获取除本身进程以外其它运行当前脚本的进程的 PIDgetExistingPIDs(){selfPID="$1"scriptFile="$2"ps -ef | grep "/usr/bin/ksh ${scriptFile}" | grep -v "grep" | awk "{ if(\$2!=$selfPID) print \$2 }"}doItsTask(){echo "Task is now being executed..."
sleep 20 #睡眠 20s,以模拟脚本在执行需要
长时间完成的任务}main $*

清单 4. 防止脚本重复运行方法 2

#!/usr/bin/kshmain(){selfPID="$$"scriptFile="$0"typeset existingPidexistingPid=`getExistingPIDs $selfPID "$scriptFile"`if [ ! -z "$existingPid" ]; then echo "The script already running, killing it..." kill -9 "$existingPid" #此方法有一定风险,慎用!fidoItsTask}#获取除本身进程以外其它运行当前脚本的进程的 PIDgetExistingPIDs(){selfPID="$1"scriptFile="$2"ps -ef | grep "/usr/bin/ksh ${scriptFile}" | grep -v "grep" | awk "{ if(\$2!=$selfPID) print \$2 }"}doItsTask(){echo "Task is now being executed..."sleep 20 #睡眠 20s,以模拟脚本在执行需要长时间完成的任务}main $*

时间: 2024-09-28 03:20:58

以Korn Shell为例分享脚本开发中的常见问题的相关文章

分享Python开发中要注意的十个小贴士_python

大家请注意:这篇文中假设我们都用的是Python 3 1. 列表推导式 你有一个list:bag = [1, 2, 3, 4, 5] 现在你想让所有元素翻倍,让它看起来是这个样子: [2, 4, 6, 8, 10] 大多初学者,根据之前语言的经验会大概这样来做 bag = [1, 2, 3, 4, 5] for i in range(len(bag)): bag[i] = bag[i] * 2 但是有更好的方法: bag = [elem * 2 for elem in bag] 很简洁对不对?这

分享Android开发中最有效率最快的循环代码

/* 1 ( 最快 ) */ for (int i = initializer; i >= 0; i--) { ... } /* 2 第二 */ int limit = calculateLoopLimit(); for (int i = 0; i < limit; i++) { ... } /* 3 */ Type[] array = getMyArray(); for (Type obj : array) { ... } /* 4 */ for (int i = 0; i < arr

动态网页制作技术ASP开发中的常见问题

动态|网页|问题 <table style="TABLE-LAYOUT: fixed" width="200" border="0" cellspacing="0" cellpadding="7" bgcolor="#f7f7f7"> <tr> <td style="LEFT: 0px; WIDTH: 100%; WORD-WRAP: break-

Asp及Web开发中的常见问题

表格的折行处理. <table style="TABLE-LAYOUT: fixed" width="200" border="0" cellspacing="0" cellpadding="7" bgcolor="#f7f7f7"> <tr> <td style="LEFT: 0px; WIDTH: 100%; WORD-WRAP: break-

asp开发中textarea常见问题

近日在作新闻的后台管理系统,在将access数据导入到SQL SERVER2000中,便出现了好多问题,现总结如下:使用SQL SERVER的[导入]功能,便可将access数据转换,但要注意原来的'自增字段'需要修改,将相应字段标识修改为'是'(原来的备注字段也会自动转化为ntext).由于新闻的添加,修改都是通过使用textarea,首先为了能保留输入内容的格式,在处理添加的页面加入<%Function SqlStr( data ) SqlStr = "'" & Re

Winform开发中手写签名的实现

由于项目的需要,需要在项目的Winform系统的一个模块中集成手写签名的功能,一开始对这块不是很了解,只是了解他能够替代鼠标进行签名.既然是签名,一般就是需要记录手稿图片,作为一个记录核实的凭证,因为有效的签名是很难模拟的.市场上也存在很多类型的电子签名笔,一时间还真不知道那种适合.本文主要从签名笔的选型以及功能实现等方面来对实现这个需求进行分析介绍,希望能够给有同样际遇的朋友一个参考. 1.电子手写签名介绍 电子手写签名,其实就是模拟真实的笔进行签名的过程,我这里主要是介绍使用外部设备来记录手

分享Android开发自学笔记之AndroidStudio常用功能_Android

相关下载: Android Studio v1.3 官方最新版(apk应用开发工具) http://www.jb51.net/softs/83206.html Android Studio 官方最新版下载地址(支持国内下载)http://www.jb51.net/softjc/83204.html 一.界面区介绍 1.项目组织结构区,用于浏览项目文件,默认Project以Android组织方式展示. 2.设计区,默认在打开布局文件时为设计模式,可直接拖动控件到界面上实现所见即所得,下方的Desi

基于WebService的性能测试脚本开发

基于WebService的性能测试脚本开发 WebService是一种构架应用程序的普遍模型,是系统对外的接口.可以在任何支持网络通信的操作系统中实施运行.WebService的主要目标就是实现应用间的跨平台的互操作.Web Service可以使系统中孤立的站点之间能够相互通信.共享资源而提出的一种接口.Web Service所常用的协议标准,包含如HTTP.XML.SOAP.WSDL等,选择WebService协议进行测试,可以使服务的客户端与系统提供的服务本身之间进行紧密耦合,达到测试的要求

Android开发中一个简单实用的调试应用技巧分享

前言 大家应该都有所体会,在应用开发中,我们常常会进行日志打印或者debug调试,以此来分析运行时的一些信息,便于发现bug和问题.Android Studio的Debug功能很好用,但是有时候有些情况下,就显得不是那么快捷和便利. 比如 我们调试的点在应用一打开的时候,很靠前,例如Application的onCreate方法中,以至于我们不能足够快的设置进程为debug模式 虽然上面的情况可以通过Android Studio的debug运行来解决,但是如果项目很大的话,运行起来也会比较耽误时间