【问题标题】:whether a shell script can be executed if another instance of the same script is already running如果同一脚本的另一个实例已经在运行,是否可以执行 shell 脚本
【发布时间】:2016-06-08 03:47:51
【问题描述】:

我有一个 shell 脚本,通常一次运行将近 10 分钟,但我需要知道在脚本实例已经运行时是否有另一个运行脚本的请求出现,新请求是否需要等待现有的要完成的实例,否则将启动一个新实例。

只要同一脚本的请求可用,我就必须启动一个新实例。

怎么做...

shell脚本是一个轮询脚本,它在目录中查找文件并执行该文件。文件的执行需要将近10分钟或更长时间。但是在执行过程中如果有新文件到达,它也必须执行同时。

shell脚本如下,以及如何修改它以执行多个请求..

#!/bin/bash

while [ 1 ]; do
 newfiles=`find /afs/rch/usr8/fsptools/WWW/cgi-bin/upload/ -newer /afs/rch/usr$
 touch /afs/rch/usr8/fsptools/WWW/cgi-bin/upload/.my_marker

 if [ -n "$newfiles" ]; then
   echo "found files $newfiles"
   name2=`ls /afs/rch/usr8/fsptools/WWW/cgi-bin/upload/ -Art |tail -n 2 |head $
    echo " $name2 "
     mkdir -p  -m 0755 /afs/rch/usr8/fsptools/WWW/dumpspace/$name2
     name1="/afs/rch/usr8/fsptools/WWW/dumpspace/fipsdumputils/fipsdumputil -e -$
  $name1
  touch /afs/rch/usr8/fsptools/WWW/dumpspace/tempfiles/$name2
   fi
   sleep 5
   done

【问题讨论】:

  • 显示shell脚本可能吗?
  • 感谢您添加脚本。显然它还没有工作,但我也无法弄清楚它实际上是什么for。事情似乎从底部开始变得非常不稳定,您在其中分配 name1 而不关闭报价。那是复制粘贴错误吗?您能否查看并修复它,并解释此脚本的上下文以及它应该实现的目标?
  • 实际上脚本在目录中查找新文件,然后它必须以新文件的名称创建一个新目录。name1 只不过是调用一个名为 fipsdumputil 并带有参数的 shell 脚本,完成执行几乎需要10分钟,在此期间如果有任何新文件也必须执行,如何完成。
  • fipsdumputil(name1) 几乎需要10分钟才能完成它的执行,是否可以将它从当前脚本中分离到一个单独的新脚本中,以便运行新文件的多个实例.

标签: shell


【解决方案1】:

在编写您所描述的脚本时,我采用两种方法之一。

首先,您可以使用 pid 文件来指示不应运行第二个副本。例如:

#!/bin/sh

pidfile=/var/run/$(0##*/).pid

# remove pid if we exit normally or are terminated
trap "rm -f $pidfile" 0 1 3 15

# Write the pid as a symlink
if ! ln -s "pid=$$" "$pidfile"; then
  echo "Already running. Exiting." >&2
  exit 0
fi

# Do your stuff

我喜欢使用符号链接来存储 pid,因为编写符号链接是一个原子操作;两个进程不能相互冲突。您甚至不需要检查 pid 符号链接是否存在,因为 ln 的失败清楚地表明无法设置 pid。这要么是权限或路径问题,要么是由于符号链接已经存在。

第二个选项是让它成为可能......不,最好......不要阻止其他实例,而是配置该脚本所做的任何事情以允许多个服务器同时在不同的队列条目上运行。 “Single-queue-single-server”永远不如“single-queue-multi-server”。由于您的问题中没有包含代码,我无法知道这种方法是否对您有用,但这里有一些解释性的元 bash:

#!/usr/bin/env bash

workdir=/var/tmp   # Set a better $workdir than this.

a=( $(get_list_of_queue_ids) )  # A command? A function? Up to you.

for qid in "${a[@]}"; do

  # Set a "lock" for this item .. or don't, and move on.
  if ! ln -s "pid=$$" $workdir/$qid.working; then
    continue
  fi

  # Do your stuff with just this $qid.
  ...

  # And finally, clean up after ourselves
  remove_qid_from_queue $qid
  rm $workdir/$qid.working

done

这样做的效果是将“一次一个”的想法从处理程序转移到数据。如果您有一个多 CPU 系统,您可能有足够的容量同时处理多个队列条目。

【讨论】:

  • 实际上我需要在请求上运行具有不同数据的同一脚本的多个实例。有没有可能
  • 一切皆有可能。如果您需要脚本方面的帮助,请联系包含该脚本的ask a question。我上面的第二个代码示例演示了如何编写可以多次运行的内容,同时从同一个队列中清除条目。
  • 我已将脚本添加到问题中,你能告诉我如何修改它以便我可以运行多个实例
  • 你能告诉如何修改它可以同时接受多个请求
  • @DDK,我对您的环境了解不多,无法推荐“最佳”解决方案。但是here's an approach 我用来解决可能是类似问题的问题。
【解决方案2】:

ghoti's answer 展示了一些有用的技术,如果可以选择修改脚本的话。

一般来说,对于一个现有的脚本:

除非你确定:

  • 除了输出到终端或写入具有特定于 shell 实例名称的文件(例如将当前 shell 的 PID $$ 合并到文件名中)或其他一些实例之外,该脚本没有任何副作用- 特定位置,

  • 或者该脚本是为并行执行而明确设计的,

我假设您不能安全地同时运行脚本的多个副本。

期望普通的 shell 脚本是为并发使用而设计的。

【讨论】:

    【解决方案3】:

    从操作系统的角度来看,多个进程当然可以并行执行同一个程序。不用担心这个。

    但是, 可以想象,一个(粗心的)程序员以这样一种方式编写程序,当两个副本并行执行时,它会产生不正确的结果。

    【讨论】:

    • 这并没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方留下评论。 - From Review
    • @CindyMeister:我认为它确实回答了这个问题。如果我理解正确的问题,OP 想知道,是否可以在同一脚本的另一个实例已经运行时运行脚本。答案是:从操作系统的角度来看,这是可能的。这是我回答的。我错过了什么吗?
    猜你喜欢
    • 2017-03-28
    • 2011-06-13
    • 2013-05-24
    • 2016-09-29
    • 1970-01-01
    • 1970-01-01
    • 2018-04-24
    • 1970-01-01
    相关资源
    最近更新 更多