shell脚本模板 [英] shell script templates

查看:225
本文介绍了shell脚本模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这将是您的建议有一个良好的bash / KSH脚本模板作为一个标准,所有新创建的脚本中使用?

what would be your suggestions for a good bash/ksh script template to use as a standard for all newly created scripts?

我通常开始(后#!行)与一个文件名,故事大纲,用法,返回值,作者(S),一个的changelog注释掉头和将融入80字符线。

I usually start (after #! line) with a commented-out header with a filename, synopsis, usage, return values, author(s), changelog and would fit into 80-char lines.

所有的文件系我开始双哈希符号:##,这样我就可以很容易地用grep他们和局部变量的名称与__

all documentation lines I start with double-hash symbols : "##", so I can grep for them easily and local var names are prepended with "__".

任何其他最佳做法?提示?命名约定?怎么样回报codeS?

any other best practices? tips? naming conventions? what about return codes?

感谢

编辑:关于版本控制的意见:我们得到了SVN所有的权利,但在企业的另一个部门有一个单独的回购,这是他们的脚本 - 我怎么知道谁带Q的联系,如果没有@author信息?的javadoc相似的条目甚至在外壳方面,恕我直言有些好处,但我可能是错的。感谢您回应

edit : comments on version control : we got svn all right, but another dept in the enterprise has a separate repo and this is their script - how do I know who to contact with Q's if there is no @author info? javadocs-similar entries have some merit even in the shell context, IMHO, but I might be wrong. thanks for responses

推荐答案

我诺曼的答案扩展到6线,最后那些空白:

I'd extend Norman's answer to 6 lines, and the last of those is blank:

#!/bin/ksh
#
# @(#)$Id$
#
# Purpose

第三行是一个版本控制标识字符串 - 它实际上是用SCCS标记的混合 @(#),可以由(SCCS)标识节目什么和RCS版本字符串文件时RCS下把它扩大,我用我的私人使用默认的VCS。该RCS计划识别拿起 $编号$ 的扩展形式,它可能看起来像 $编号:mkscript.sh,v 2.3 2005/05/19 21时06分35秒jleffler精通$ 。第五行提醒我,该脚本应该有它的顶部用途的说明;我用脚本的实际描述(这就是为什么有后没有冒号,例如)一词取代。

The third line is a version control identification string - it is actually a hybrid with an SCCS marker '@(#)' that can be identified by the (SCCS) program what and an RCS version string which is expanded when the file is put under RCS, the default VCS I use for my private use. The RCS program ident picks up the expanded form of $Id$, which might look like $Id: mkscript.sh,v 2.3 2005/05/20 21:06:35 jleffler Exp $. The fifth line reminds me that the script should have a description of its purpose at the top; I replace the word with an actual description of the script (which is why there's no colon after it, for example).

在这之后,有本质上不过标准的shell脚本。有迹象表明,出现标准的片段,而是出现在每个脚本没有标准的片段。 (我的讨论假设脚本编写的伯恩,Korn或POSIX(bash)的外壳符号。有一个关于为什么有人把一个C shell衍生而来的#后!印记的同居生活。)

After that, there is essentially nothing standard for a shell script. There are standard fragments that appear, but no standard fragment that appears in every script. (My discussion assumes that scripts are written in Bourne, Korn, or POSIX (Bash) shell notations. There's a whole separate discussion on why anyone putting a C Shell derivative after the #! sigil is living in sin.)

例如,这code出现在某种形式每当脚本创建中间(临时)文件:

For example, this code appears in some shape or form whenever a script creates intermediate (temporary) files:

tmp=${TMPDIR:-/tmp}/prog.$$
trap "rm -f $tmp.?; exit 1" 0 1 2 3 13 15

...real work that creates temp files $tmp.1, $tmp.2, ...

rm -f $tmp.?
trap 0
exit 0

第一行选择一个临时目录,默认为,如果用户没有指定替代的/ tmp目录($ TMPDIR非常广泛认可,并通过POSIX标准)。然后创建一个文件名preFIX包括进程ID。这不是一种安全措施;它是从践踏彼此的数据脚本的简单并发措施,preventing多个实例。 (为了安全起见,在一个非公开的目录中使用非predictable文件名。)第二行确保 RM 出口'命令的执行(2),SIGQUIT(3),SIGPIPE(13)或SIGTERM(15)。在 RM 命令删除匹配模板,任何中间文件;在退出命令确保地位不为零,表明某种错误。在陷阱'的0意味着如果shell退出以任何理由code也执行 - 它涵盖疏忽的部分标有真正的工作。然后在最后的code之前的删除任何幸存的临时文件,的取消对出口的陷阱,最后用一个零(成功)状态退出。很显然,如果你想与另一个状态退出,您可能 - 只要确保您运行 RM 陷阱线,然后用退出$ exitval

The first line chooses a temporary directory, defaulting to /tmp if the user did not specify an alternative ($TMPDIR is very widely recognized and is standardized by POSIX). It then creates a file name prefix including the process ID. This is not a security measure; it is a simple concurrency measure, preventing multiple instances of the script from trampling on each other's data. (For security, use non-predictable file names in a non-public directory.) The second line ensures that the 'rm' and 'exit' commands are executed if the shell receives any of the signals SIGHUP (1), SIGINT (2), SIGQUIT (3), SIGPIPE (13) or SIGTERM (15). The 'rm' command removes any intermediate files that match the template; the exit command ensures that the status is non-zero, indicating some sort of error. The 'trap' of 0 means that the code is also executed if the shell exits for any reason - it covers carelessness in the section marked 'real work'. The code at the end then removes any surviving temporary files, before lifting the trap on exit, and finally exits with a zero (success) status. Clearly, if you want to exit with another status, you may - just make sure you set it in a variable before running the rm and trap lines, and then use exit $exitval.

我通常使用以下方法来删除该脚本的路径和后缀,这样我就可以使用 $为arg0 报告错误时:

I usually use the following to remove the path and suffix from the script, so I can use $arg0 when reporting errors:

arg0=$(basename $0 .sh)

我经常使用shell函数来报告错误:

I often use a shell function to report errors:

error()
{
    echo "$arg0: $*" 1>&2
    exit 1
}

如果只有一个或者两个错误退出,我不与理会的功能;如果有任何更多的,我这样做,因为它简化了编码。我也创造了或多或少的精细功能叫做使用给如何使用该命令的总结 - 再一次,只有在有一个以上的地方,它会使用

If there's only one or maybe two error exits, I don't bother with the function; if there are any more, I do because it simplifies the coding. I also create more or less elaborate functions called usage to give the summary of how to use the command - again, only if there's more than one place where it would be used.

另一个相当标准的片段是一个选项解析循环,使用 getopts的外壳内置:

Another fairly standard fragment is an option parsing loop, using the getopts shell built-in:

vflag=0
out=
file=
Dflag=
while getopts hvVf:o:D: flag
do
    case "$flag" in
    (h) help; exit 0;;
    (V) echo "$arg0: version $Revision$ ($Date$)"; exit 0;;
    (v) vflag=1;;
    (f) file="$OPTARG";;
    (o) out="$OPTARG";;
    (D) Dflag="$Dflag $OPTARG";;
    (*) usage;;
    esac
done
shift $(expr $OPTIND - 1)

shift $(($OPTIND - 1))

在争论围绕$ OPTARG处理空间的报价。该DFLAG是累积的,但这里所用的符号失去跟踪的争论空间。有(非标准)方法可以解决这个问题了。

The quotes around "$OPTARG" handle spaces in arguments. The Dflag is cumulative, but the notation used here loses track of spaces in arguments. There are (non-standard) ways to work around that problem, too.

第一个转变符号与任何外壳工程(或者,如果我用会做反单引号,而不是 $(...)。在现代的第二个作品贝壳;甚至有可能是用方括号而非小括号替代,但是这个工作,所以我已经没有尽力去找出那是什么

The first shift notation works with any shell (or would do if I used back-ticks instead of '$(...)'. The second works in modern shells; there might even be an alternative with square brackets instead of parentheses, but this works so I've not bothered to work out what that is.

现在最后一个诀窍是,我经常都在GNU和非GNU版本的方案过来,我希望能够选择我用。我的许多脚本,因此,使用变量如:

One final trick for now is that I often have both the GNU and a non-GNU version of programs around, and I want to be able to choose which I use. Many of my scripts, therefore, use variables such as:

: ${PERL:=perl}
: ${SED:=sed}

然后,当我需要调用Perl或 SED ,脚本使用 $ PERL $ SED 。这可以帮助我,当东西的行为有所不同 - 我可以选择的操作版本 - 或者在开发脚本(我可以在不修改脚本添加额外的仅调试选项命令)

And then, when I need to invoke Perl or sed, the script uses $PERL or $SED. This helps me when something behaves differently - I can choose the operational version - or while developing the script (I can add extra debug-only options to the command without modifying the script).

这篇关于shell脚本模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆