shell脚本代码 - 无法理解

时间:2014-03-27 14:30:12

标签: bash shell

我想了解这段代码,因为我是shell脚本的初学者

1  #!/bin/bash
2 PATH=$PATH:/bin:/usr/bin
3
4
5 TMP_FILE=/tmp/i_am_running
6 [ -f $TMP_FILE ] && exit
7 touch $TMP_FILE
8
9
10 /usr/bin/python /home/ahmed/Desktop/python.py
11 rm $TMP_FILE
  1. 为什么我们使用第1行和第2行?
  2. 我刚刚学会了if then else结构

    如果 然后 网络

  3. 我们不能在该结构中转换第6-7行吗?

4 个答案:

答案 0 :(得分:1)

第1行不应缩进;第一个字符应为#。它告诉内核在这种情况下使用命名解释器/bin/bash来执行此程序。如果您愿意,可以在宽范围内指定任何可执行文件(不是脚本)作为解释器。

第2行正在防止荒谬;如果有人没有/bin/usr/bin的PATH设置,那么他们已经遇到了某种麻烦。但是,这可以确保它们存在。 (请注意,在Solaris上,/bin/usr/bin的符号链接,因此$PATH中不需要两者,但是肯定会有一个或那个。)

是的,您可以将第6-7行转换为:

if [ -f "$TMP_FILE" ]
then exit
fi
touch "$TMP_FILE"

如果系统中只有一个用户,则您选择的锁定文件名称就足够了,但它不适合更广泛使用的程序(两个人不能同时使用该文件)。

您可以通过添加trap命令来清理临时文件来改进代码:

trap "rm -f '$TMP_FILE'; exit 1" 0 1 2 3 13 15
…commands…
rm -f "$TMP_FILE"
trap 0

如果您编程崩溃或被中断,这将删除临时文件。

答案 1 :(得分:1)

  1. 第一行是所谓的shebang。它告诉任何尝试运行文件如何运行它。第二行通过将/bin/usr/bin添加到该变量,确保xx$PATH上,因此如果$PATHif,则只需运行命令if [ -f $TMP_FILE ] then exit fi 即可在这两个目录之一(或{{1}}中已有的其他目录)。

  2. 第6行和第7行实际上并没有任何关系。第6行本身可以变成{{1}}语句:

    {{1}}

答案 2 :(得分:1)

我会逐行:

1:这似乎是一个缺陷:#之前不应该有空格。无论如何,它是一个" shebang line"它告诉使用什么口译员。如果用户希望在非默认版本的bash下运行,有些人会更愿意看到#!/usr/bin/env bash,这会提供更大的灵活性。

5:创建一个包含路径的变量。

6:[ -f $TMP_FILE ] && exit表示"如果文件存在,退出(使用成功代码,即0)。"你是对的,它可以写成" if"声明。另请注意,[ -f $TMP_FILE ]实际上是test -f $TMP_FILE的简写;了解这一点,您可以查看man test以了解各种选项。

7:现在我们知道该文件不存在,我们创建它。或者至少我们尝试 - 由于各种原因,这可能会失败,并且不会检查返回码!最好将set -e放在任何shell脚本的顶部,这意味着如果有未经检查的失败代码则停止。"

10:接下来我们运行Python。不是用户选择的Python解释器,而是具体的是/ usr / bin /。同样,这不是最佳实践 - 最好是在Python脚本本身的顶部有一个#!/usr/bin/env python shebang行,并直接调用它,允许用户的环境选择所需的Python解释器。

11:现在我们删除$ TMP_FILE,这将允许我们下次再次运行。因此它是一种锁定文件,"虽然不是一个非常强大的实施。例如,如果用户在Python脚本运行时按Ctrl-C中断脚本会发生什么?锁定文件将被遗忘。在这种情况下退出之前,您可以使用Bash中的trap内置来删除锁定文件。

也许你应该直接在Python中集成锁文件功能,并摆脱这个包装脚本。您可以将它放在Python脚本的顶部,然后完全删除包装器:

import errno
import fcntl
import sys

lockfile = open('/tmp/i_am_running', 'a')
try:
      fcntl.flock(lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
except IOError as ex:
      if ex.errno == errno.EWOULDBLOCK:
            sys.exit("oops, already running")
      else:
            raise

# now the file is locked, do whatever you need and it will unlock on exit

最后请注意,Linux系统上这样的锁定文件的规范位置在/var/run/下,而不是/tmp/

答案 3 :(得分:1)

1 #!/bin/bash
2 PATH=$PATH:/bin:/usr/bin
3
4
5 TMP_FILE=/tmp/i_am_running
6 [ -f $TMP_FILE ] && exit
7 touch $TMP_FILE
8
9
10 /usr/bin/python /home/ahmed/Desktop/python.py
11 rm $TMP_FILE
  1. 第一行:指定解释器,即使用bash
  2. 执行
  3. 第二行:将/bin/usr/bin添加到环境变量PATH(未正常使用),这可能是因为有人将其从PATH中移除。
  4. 6-7行:如果文件/tmp/i_am_running存在,请退出。否则,创造它。见this post。 您可以使用if-else来执行此操作:

    if [ -f "$TMP_FILE" ]
    then
        exit
    fi
    touch "$TMP_FILE"
    
  5. 10-11行:运行程序python.py并删除$ TMP_FILE