LoginSignup
8
6

More than 5 years have passed since last update.

Linuxでマルチプロセスなスクリプトをサクッと作る!

Posted at

背景

数万件のバッチ処理を回したいのだけど、シーケンシャルにしか処理されず時間がかかってしょうがないってことありますよね。
自分はこの前そうでした。
手っ取り早くマルチプロセスにするためのバッチを書いたら思いのほか使い勝手が良かったのでこちらにメモって置くことにします。

環境

Centos7
Perl5.x

やりたいこと

  • 数万件のデータ処理
  • 1件の処理自体はコマンド一発
  • 入力データは1ファイルに纏めて、各プロセスが参照されるようにしたい
  • 非エンジニアでも簡単にプロセス数を調整したい
  • 個人的な趣味によりPerlで実装したけどなんでも良い

アプローチ

bashでマルチプロセス処理をさせる簡単な方法は&を使ってバックグラウンド処理させたり、xargs -Pを使う方法があるけど、今回は入力データは1ファイルにまとめておきたく、ロック処理が必要なため手組みで実装することにした。

処理としてはシンプルで
1. ロックフォルダを作成する
2. インプットファイルからデータを読み込む
3. 読み込んだデータをインプットファイルから削除する
4. ロックフォルダを削除する
5. 読み込んだデータを処理する

という流れ

で、作った雛形がこれ

Perlで書いてるけどなんでも良いと思う。

process.pl
#!/usr/bin/perl
use strict;
use Time::HiRes qw/sleep/;
use feature 'say';

my $lock="lock";
my $input="input.txt";
my $n=10;
my $waitTime=0.2;

while(1){
    # create lock folder
    if( system("mkdir $lock &> /dev/null") ){
        say "wait...";
        sleep $waitTime;
        next;
    }

    # read the first $n rows.
    my @list= split("\n", `head -n $n $input`);

    # remove the read line
    `sed -i -e '1,${n}d' $input`;

    # unlock
    `rmdir $lock`;

    # program exit if the read rows is empty
    if( int @list == 0 ){ last; }

    # process the read rows
    foreach my $line (@list){
        unless( $line =~ /\S/ ){ next; }
        chomp $line;
        $line =~ s/(^")|("$)//g;

        my @cmd_parts = ();
        push( @cmd_parts, 'curl -s' );
        push( @cmd_parts, '-X DELETE' );
        push( @cmd_parts, "'http://xxx.xxx.xxx.xxx/$line'" );

        my $cmd = join( " ", @cmd_parts);
        my $result = `$cmd`;
        say $cmd;

    }

sleep 5;
}

使い方

input.txtに処理するデータを改行区切りで格納しておく。
あとは perl process.pl >> app1.log &って感じでバックグラウンド実行する。多重度を上げたかったらログ出力先をapp2.logapp3.logと変えて同じコマンドを実行していく。
ログ出力先が同じでも動作するけど、複数のプロセスが1つのファイルとIOするとIO競合が発生してログの欠損などがでるので別にするのが安全。

8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6