暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Linux 删除大量小文件 -- AI方案

生有可恋 2023-10-23
425

以前是“内事不决问baidu,外事不决问google”,现在多了一个选择,可以问AI。比如删文件这件事,当文件数达到亿级别,光输出目录下的文件名列表,日志文件大小都可以达到G级别。当数据量大了之后,执行串行 rm 操作将花费大量的时间删文件,只有通过增加并发才能减少所花费的时间。

通过 Python 写多进程或多线程脚本,控制 rm 删除操作的并发数这可很好地解决这个问题。但这样会额外引入不必要的复杂度,如果能用一条命令就解决就更好了。毕竟删文件,方法越简单越好。

问 AI 在 bash 脚本中如何控制并发?AI 给出了四种方案,都很有道理。

方案一:使用 & 后台运行

在Bash脚本中使用&符号将任务置于后台运行,从而实现并发执行。

例如:

    # 启动任务1后台运行
    task1 &


    # 启动任务2后台运行
    task2 &


    # 等待任务1和任务2完成
    wait


    方案二:使用 sem 命令


    使用sem命令,它允许您指定并发任务的数量。首先,您需要安装sem工具,然后可以在Bash脚本中使用它。

    以下是一个示例:

      # 安装 sem 工具
      sudo apt-get install parallel


      # 使用 sem 控制并发任务
      max_jobs=4
      sem -j $max_jobs your_command_1
      sem -j $max_jobs your_command_2
      sem -j $max_jobs your_command_3
      sem --wait


      方案三:使用 xargs 命令

      使用xargs命令来控制并发任务。

      例如:

        # 使用 xargs 控制并发任务
        max_jobs=4
        cat command_list | xargs -P $max_jobs -I {} bash -c '{}'


        这将使用xargs命令并行执行命令列表,最多允许4个并发任务。

        方案四:使用 GNU Parallel:

        GNU Parallel是一个强大的工具,可以用于并行执行任务。可以创建一个文本文件 commands.txt 包含一系列命令,使用 -j 选项,您可以指定允许同时运行的任务数。

          例如,要限制最多同时执行 4 个任务:
          parallel -a commands.txt -j 4


          方案一无法控制大量任务,方案二和四要额外安装软件。我选择方案三,并让 AI 解释方案三中的命令都是什么意思。

            # 使用 xargs 控制并发任务
            max_jobs=4
            cat command_list | xargs -P $max_jobs -I {} bash -c '{}'

            以上命令解释如下:

            • -P 选项后面跟着一个数字代表您想要的最大并发任务数。

            • -I {} 这部分告诉xargs如何将输入的数据插入到命令中‘{}’是一个占位符,xargs会将每个命令依次插入到{}的位置。

            • bash -c '{}': 这部分是要执行的命令,其中{}将被xargs替换为command_list中的命令。


            可以构造一个随机耗时脚本来测试并发,验证通过后来再用来删文件。使用随机数模拟并发中的程序耗时,脚本如下:

              #!/bin/bash
              # tmp/sleep.sh
              min=1
              max=100
              random_number=$((min + RANDOM % (max - min + 1)))


              echo sleep $random_number
              sleep $random_number

              再构造一下命令列表:

                for i in $(seq 1 100); do
                echo "bash tmp/sleep.sh" >> /tmp/command_list
                done

                最后使用 xargs 调用命令列表:

                  $ max_jobs=4
                  $ cat /tmp/command_list | xargs -P $max_jobs -I {} bash -c '{}'
                  sleep 87
                  sleep 28
                  sleep 44
                  sleep 40


                  通过执行测试命令可以看出每次执行四条命令,当有命令提前执行完成时,xargs 会将任务数补充至所要求的最大并发数 max_jobs

                  在测试命令中所使用的 -I {} 是占位符,我们可以使用其它占位符替代,比如命令可以写成:

                    $ cat /tmp/command_list | xargs -P $max_jobs -I @@ bash -c '@@'

                    我们也可以将 bash -c 换成 echo 命令,测试我们将要执行的命令。echo 将会将占位符的内容打印出来,方便我们核对命令是否正确。删除操作是非常危险的,执行前一定要再三确认。

                    下面正式开始我们的删除任务,所要删除的文件都在一级目录,我们将要删除的一级目录通过 find 命令构造一个删除任务列表:

                      $ find sync/trans/192.168.10.23/pacs/172.16.100.68 \
                      -mindepth 2 \
                      -maxdepth 2 \
                      -type d \
                        | awk '{print "rm -rf "$1}' \
                      | tee tmp/command_list

                      最终任务列表如下:

                        bash$ cat tmp/command_list
                        rm -rf /sync/trans/192.168.10.23/pacs/172.16.100.68/images/20201217_20
                        rm -rf /sync/trans/192.168.10.23/pacs/172.16.100.68/images/20201123_20
                        rm -rf /sync/trans/192.168.10.23/pacs/172.16.100.68/images/20201212_20
                        rm -rf /sync/trans/192.168.10.23/pacs/172.16.100.68/images/20201214_20
                        rm -rf /sync/trans/192.168.10.23/pacs/172.16.100.68/images/20201009_20


                        因为任务会长时间运行,在正式执行前先启动一个 screen  会话,用来维持运行的环境。

                          $ screen -S rm_task

                          在 screen 会话中执行删除任务:

                            $ cat /tmp/command_list | xargs -P 8 -I @@ echo '@@'

                            在执行前用 echo 命令测试了一个命令是否正确,然后将 echo 换成 bash -c 正式执行:

                              $ cat /tmp/command_list | xargs -P 8 -I @@ bash -c '@@'

                              实际执行时并没有命令输出,因为 rm 操作没有输出。之前的 sleep 命令有输出是因为通过脚本包装了一层,执行前输出了要执行的命令。如果要查看当前命令是否正在执行,可以通过 ps 命令查看:

                                $ ps -eaf| grep rm
                                pts/1 00:00:03 rm -rf /sync/trans/192.168.10.23/pacs/172.16.100.68/images/20201202_20
                                pts/1 00:00:05 rm -rf /sync/trans/192.168.10.23/pacs/172.16.100.68/images/20210119_20
                                pts/1 00:00:03 rm -rf /sync/trans/192.168.10.23/pacs/172.16.100.68/images/20201129_20
                                pts/1 00:00:03 rm -rf /sync/trans/192.168.10.23/pacs/172.16.100.68/images/20201218_20
                                pts/1 00:00:03 rm -rf /sync/trans/192.168.10.23/pacs/172.16.100.68/images/20201209_20
                                pts/1 00:00:03 rm -rf /sync/trans/192.168.10.23/pacs/172.16.100.68/images/20201213_20
                                pts/1 00:00:03 rm -rf /sync/trans/192.168.10.23/pacs/172.16.100.68/images/20201127_20
                                pts/1 00:00:03 rm -rf /sync/trans/192.168.10.23/pacs/172.16.100.68/images/20200907_20

                                通过 ps 命令可以看到并发的 rm 操作有 8 个,这些任务都是 xargs 的子进程:

                                  $ pstree -p 
                                  screen(15040)───bash(15043)───xargs(1743)─┬─rm(1744)
                                  ├─rm(1745)
                                  ├─rm(1746)
                                  ├─rm(1747)
                                  ├─rm(1748)
                                  ├─rm(1749)
                                  ├─rm(1750)
                                  └─rm(1751)


                                  注意

                                  删除操作是一个风险极高的操作,在使用你不了解的技术前一定要多多验证,一个空格可能就会造成删盘的惨案。

                                  以上技巧除了可用来构造大量小文件的删除操作外,也可用于构造小文件的拷贝、验证任务。低成本的并发控制可以少写不少代码,之前用python构造的小文件并发拷贝任务的文章可以作为参考:

                                  通过增加并发提高小文件传输速度

                                  全文完。

                                  如果转发本文,文末务必注明:“转自微信公众号:生有可恋”。


                                  文章转载自生有可恋,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                  评论