账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回 手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    shell解决一个竞争问题
    24
    0

    我有如下脚本upgrade.sh,前端页面通过php调用,但多个页面间可以同时调用,比如升级时php端先执行--download,在download前都可以取消,download完成后,然后再调用install_pkg(在install_pkg时不可取消),现在download下来的包如何存放才能避免并发逻辑?

    我现在是php端调用了./upgrade.sh --download之后,我将下载的pkg包路径(包含文件名)写入到固定文件中,下载的包存放在随机目录中,然后php再调用./upgrade.sh --install去安装。安装的时候我执行--install去获取我们保存pkg路径信息,然后去安装。

    之所以需要调用两次脚本,分开是因为要支持取消升级。如果写在一个流程里无法实现取消升级的操作。

    由于php要调用两次,所以也不能用单例模式,如果只需要调一次,那么就可以通过单例实现同时只调用一次。被这个问题折磨一天,写得乱七八糟,希望各位能给点意见。

    function main()
    {
        if [ "$1" == "--download" ]; then
            download_pkg 
        elif [ "$1" == "--install" ]; then
            install_pkg      
        else
            usage
        fi
    }
    main $@
    0
    打赏
    收藏
    点击回答
        全部回答
    • 0
    • 麽麽茶 普通会员 1楼

      在Shell中解决竞争问题通常涉及到进程同步和资源的管理。以下是一个简单的示例,展示如何在多个进程之间共享一个文件资源,同时防止其中一个进程试图修改另一个进程已经读取的文件内容:

      ```bash

      !/bin/bash

      获取文件路径和文件名

      file_path="$1" file_name="$2"

      初始化文件和进程列表

      files=() processes=()

      遍历目录下所有可读文件

      for file in "$file_path"/*.txt; do # 如果文件不存在或为文本文件,则忽略 if [ ! -f "$file" ] || [ ! -i "$file" ]; then continue fi

      # 判断文件是否已读取
      if [ ! -r "$file" ]; then
          # 添加文件到进程列表
          files+=("$file")
      fi
      
      # 创建进程并启动
      p=$(pidof $file)
      p+=1
      p=($p%${processes[@]}+1)
      pids+=($p)
      
      # 检查是否有其他进程正在修改同一文件
      for process in "${processes[@]}"; do
          if [ -z "$process" ]; then
              # 启动进程
              p=$(pidof $file)
              p+=1
              p=($p%${processes[@]}+1)
              pids+=($p)
              process=$p
              break
          fi
      
          # 判断文件是否已读取
          if [ ! -r "$file" ]; then
              # 如果正在读取,阻止其修改文件
              # 可以使用umask(文件权限)来限制其他进程读取权限
              [ $p -o $process`umask 022` -o $process`umask 011` -o $process`umask 010` ] &> /dev/null
          fi
      done
      
      # 在每个进程结束时,清除进程列表和进程 ID
      for pid in "${pids[@]}"; do
          pids[$pid]=0
          pids[$pid]=0
      done
      

      done

      检查是否有其他进程正在修改同一文件

      for process in "${processes[@]}"; do if [ -z "$process" ]; then # 启动进程 p=$(pidof $file) p+=1 p=($p%${processes[@]}+1) pids+=($p) process=$p break fi

      # 检查文件是否已读取
      if [ ! -r "$file" ]; then
          # 如果正在读取,阻止其修改文件
          # 可以使用umask(文件权限)来限制其他进程读取权限
          [ $p -o $process`umask 022` -o $process`umask 011` -o $process`umask 010` ] &> /dev/null
      fi
      

      done

      删除进程

      for pid in "${pids[@]}"; do pids[$pid]=0 done

      删除进程列表

      for pid in "${pids[@]}"; do pids[$pid]=0 done ```

      在这个示例中,我们首先获取了要共享的文件路径和文件名。然后,我们创建了一个包含所有要处理的文件的列表,以及一个包含所有正在处理文件的进程列表。我们遍历文件目录下的所有可读文件,并检查它们是否已读取。如果文件尚未读取,我们将文件添加到进程列表中。然后,我们创建并启动每个进程,检查它是否正在读取文件,并在进程结束时,检查文件是否已读取,阻止它修改文件。如果文件正在读取,我们可以使用umask来限制其他进程读取权限,从而防止其他进程修改文件内容。最后,我们删除了处理过的文件列表和进程列表,以确保所有的资源都被正确地释放。

      注意,这只是一个基本示例,实际应用中可能需要根据具体的需求和环境来调整,例如使用更复杂的同步机制(如信号量、互斥锁等),处理更复杂的文件格式(如二进制文件、二进制序列文件等),以及在进程启动和结束时更精确地检查文件状态等。

    更多回答
    扫一扫访问手机版
    • 回到顶部
    • 回到顶部