【问题标题】:Bash linux force multiple instances to wait for running sqlplus command to finishBash linux强制多个实例等待运行sqlplus命令完成
【发布时间】:2016-11-04 09:10:25
【问题描述】:

我有一个允许同时运行多个实例的 bash 脚本。但是,存在到 Oracle 数据库的 sqlplus 连接以检索值。如果多个 bash 脚本实例同时获取此值,它们可能会检索到相同的值,因为当第一个实例仍在处理时,第二个实例已经在验证“旧数据”。

我只能想到两个选项,即通过 PIDFILE 锁定功能。缺点是如果用户在 pidfile 被删除之前中止操作,则会导致问题。另一个是基于声明ps -ef | grep 'scriptname' | wc -l 计数的最大进程来锁定整个脚本。但这会锁定整个脚本,而不仅仅是数据库部分。

那么还有其他选择吗?这个与数据库的 sqlplus 连接是否可以以某种方式捕获,以便我可以在其中一个实例执行此函数时暂停多个正在运行的实例?

【问题讨论】:

    标签: linux bash shell connection sqlplus


    【解决方案1】:

    您可以在 tmp 文件中使用唯一值(本例中为 /tmp/pidfile),并在脚本中止或完成时将其重置。

    更新:这看起来很可靠,请参阅底部的测试。

    #!/bin/bash
    
    
    bashpid="$$"                     # Records PID of script.  Unused so far
    pidfile=/tmp/pidfile             # pidfile var
    pidlimit=2                       # pidlimit
    
    cleanup () {                     # cleanup operations
            exit
        }
    
    pidreset () {                    # trap operations (if reqd)
            pkill -a -P "$bashpid"
            kill -9 0
        }
    
    trap "pidreset" SIGINT           # trap (if reqd)
    
    
    countpid () {                    # This is the true PID count, only called
                                     # Once allowed in the database block
                                     # This includes self instance
    
         ps aux | grep "$(basename $0)" | grep -v grep > $pidfile
    
    }
    
    countloop () {                   # This counts PID while waiting for a spot
                                     # (-1 decrement since self is included but 
                                     # not yet granted access to database block)
        echo "(( ("$(ps aux | grep "$(basename $0)" | grep -v grep | wc -l )") - 1))" | bc > $pidfile
    
    }
    databasecall () {                # The database script calls
    
        touch $pidfile
        pidcount="$(cat $pidfile | wc -l)"
        until [[ "$pidcount" -le "$pidlimit" ]]; do
            echo "too many processes"
            countloop 
            pidcount="$(cat $pidfile | wc -l)"
            sleep 5
        done
    
        #   ================  Start of Database access Code ================
        #   Go ahead and do database stuff
        #   Write this script into the pidfile incrementing its count also
    
        countpid 
        pidcount="$(cat $pidfile | wc -l)"
        echo "We're in"
        echo "Scriptcount: $pidcount (Including this one)"
        sleep 5
        cleanup
        # return / whatever
        #   ================  End of Database access Code ================
    
    }
    
    
    
    echo "Main script block"          # Main script outside of Database block
    sleep .1
    
    
    databasecall                      # Call database function
    
    
    cleanup                           # Call to housekeeping
    

    测试

    它运行良好,但运行速度比 pidlimit 多一个,但我不确定这是在哪里发生的,或者它是否是我的测试场景。

    bash>echo "imrunning & sleep .5 ; imrunning & sleep .5 ; imrunning & sleep .5 ; imrunning & sleep .5 ; imrunning" > /tmp/initrunning ; chmod +x /tmp/initrunning bash>/tmp/./initrunning 主脚本块 我们在 Scriptcount:1(包括这个) 主脚本块 我们在 Scriptcount:2(包括这个) 主脚本块 进程过多 主脚本块 进程过多 主脚本块 进程过多 我们在 Scriptcount:3(包括这个) 我们在 Scriptcount:3(包括这个) 我们在 Scriptcount:3(包括这个) 重击

    【讨论】:

    • 嗯,这肯定不会让我的脚本变得更简单哈哈。与锁定整个脚本相比非常麻烦,但我想它可以工作。我需要一些时间来测试所有这些并调整我的脚本。因此,在此之后我只学到了一个其他选项(但我还没有尝试过);是创建一个只允许 1 个连接的模式用户。无论如何,感谢您的代码、时间和精力! :)
    • @IvanM 我听到了!我更关注锁定脚本的一部分的能力,因为最初我并不清楚您是否试图严格锁定与数据库的一个连接。我最后有很多未知数,但有几个想法..,SESSIONS_PER_USER 参数会影响读取操作吗?如果你想完全限制阅读;根据性能需求 - 您可以使用 lsof -t /path/to/db.sql 来检测对文件的物理访问。
    • @IvanM 至于中止操作..为了减轻“用户中止”情况,您可以在上面的 cleanup() 部分中删除/检查/清理锁定文件。它是捕获 ctrl+c 的模板,但您可以指定任何适合来自最终用户的事件。
    • lsof 你说...这对我来说是新的。是的。为了提供更多细节,我的脚本创建了一个 .sql 文件,然后在 sqlplus-run 命令中应用它。所以使用lsof 我可以检测到这个文件正在被访问,这样第二个正在运行的实例就会被放入队列中,直到这个文件不再被访问?
    • 可以,需要自己测试。 lsof 通过内核对各种类型的打开文件描述符进行操作(请参阅man lsof)。 DB 可以使用各种方法的组合来对文件应用共享锁或排他锁。请记住,数据库锁定系统是围绕保护内部数据的完整性而设计的。限制只读实例并不常见,因为这通常使用身份验证系统或在当今使用 API 的云服务中完成。所以对于一个物理读取访问必须一次只有 1 个的小型应用程序,我建议 lsof 可能会很好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-20
    • 2015-06-13
    • 1970-01-01
    相关资源
    最近更新 更多