設定:
Linuxサーバーのリストを含むファイルを処理し、次のようにsshを介してそのリモートサーバーでbashまたはperlスクリプトを実行するPHPスクリプト(現在PHP 5.5用に作成されていますが、実行中のサーバーには7.4があります)があります。
exec("ssh -o StrictHostKeyChecking=no -p $connectivity_port $user@$server \"bash -s\" -- < $file $scriptargs 2>&1", $result, $exit_code);
これらの操作はすべてうまくいきますが、実行されるコードによっては時間がかかります。ローカルなので、スクリプト出力以外に処理することはほとんどありません(PHPを実行しているサーバー上のローカルファイルへのロギングといくつかのスクリプト出力がたくさんあります)。
ターゲット
bashで並行してPHPスクリプトを実行するための最良の/最も簡単な方法/ツールが何であるか疑問に思います。すべての出力がリスト内のサーバーの順序であることを確認してください(例:一度にxサーバー、おそらく10、実行時間を短縮)
私の研究とバージョンの制約で見ると、PHP自体は行く道ではないようですが、bashはその声明に合わないようですが、私は喜んで間違っている可能性があり、他の方法を学ぶことに興味があります。
答え1
あなたは次のことをしますbash
:
declare -r MAX_PARALLEL='5' WAITSEC='0.1'
i=0
server[i]=...
port[i]=...
user[i]=...
command_file[i]=...
scriptargs[i]=...
((i++))
server[i]=...
port[i]=...
user[i]=...
command_file[i]=...
scriptargs[i]=...
((i++))
count=$i
for((i=0;i<count;i++)); do
while [ $(jobs -r | wc -l) -gt "$MAX_PARALLEL" ]; do
sleep "$WAITSEC"
done
( ssh -o StrictHostKeyChecking=no -p "${port[i]}" "${user[i]}@${server[i]}" \
"bash -s" <"${file[i]}" "${scriptargs[i]}" >output_file.$i 2>&1
echo $? >exit_code.$i ) &
done
残念ながら、正しい作業数を得る簡単な方法はないようです。したがって、この方法はコマンドラインに改行文字が含まれていない場合にのみ正しく機能します。
答え2
Synology DS218で同様のことを実行しました。
私の場合、PHPスクリプトはさまざまなコマンドを使用してbashスクリプトを準備し、スクリプトを実行します。
これは次のように動作します。私のものケース
- すべてのサーバーは分離されています。 (サーバーに過負荷がかかりません。)
- サーバー12のエラーは、12以降のサーバーを停止してスキップすることを意味しません。
これらの要件が満たされない場合は、他の作業を実行する必要があります。
しかし、彼らがいる限りはい、
#!/bin/bash
ssh server1 "command1" > output1 2> error1 &
ssh server2 "command2" > output2 2> error2 &
...
ssh serverN "commandN" > outputN 2> errorN &
# wait for all SSHs to complete
wait
最後に、すべての出力ファイルは番号順に収集され削除されます。
答え3
パールを使用できますパラレル::ForkManagerそしてIPC::オープン2。
使用法:
cat list_of_servers.txt | perl para.pl /path/to/script.sh ARG1 ARG2
コードpara.pl
:
#!/usr/bin/env perl
use v5.20;
use IPC::Open2 qw(open2);
use Parallel::ForkManager qw();
sub run_script_on_server {
my ( $server, $script, @args ) = @_;
say "$$ running script: $script on server: $server with args: @args";
# TODO: replace with ssh invocation
my $pid = open2( my $chld_out, my $chld_in, "bash", $script, @args );
local $/ = undef;
return <$chld_out>;
}
my $pm = Parallel::ForkManager->new(10);
while ( my $server = <STDIN> ) {
$pm->start and next;
chomp $server;
my $result = run_script_on_server( $server, @ARGV );
say "$$ result from $server: $result";
$pm->finish;
}
答え4
これを行う2つの方法を提案できます。
パラメータ
改行で区切られたホスト名のリストを含むファイルがあり、使用しているすべての接続user
に対して。port
xargs
xargs -I '{}' -P <max-procs> --arg-file <INPUTFILE> bash -c "ssh -o StrictHostKeyChecking=no -p $connectivity_port $user@{} 'bash -s' < $file $scriptargs > $OUT_FOLDER/{}.log 2>&1"
or
cat <INPUTFILE> | xargs -I '{}' -P <max-procs> bash -c "ssh -o StrictHostKeyChecking=no -p $connectivity_port $user@{} 'bash -s' < $file $scriptargs > $OUT_FOLDER/{}.log 2>&1"
このフラグを使用して並行性を設定できます-P
。
--max-procs=max-procs
-P max-procs
Run up to max-procs processes at a time; the default is 1. If
max-procs is 0, xargs will run as many processes as possible at
a time. Use the -n option with -P; otherwise chances are that
only one exec will be done.
各コマンドの出力を記録します$OUT_FOLDER/$HOST.log
。
user
異なるマシンがあり、port
各マシンで引き続き使用できますが、xargs
少し複雑になります。
PDSH
別のオプションは、次のものを使用することです。pdsh
「並列にホストグループにコマンドを実行できます。」
pdsh -R exec -w^<INPUT FILE> -f <max-procs> bash -c "ssh -o StrictHostKeyChecking=no -p $connectivity_port %u@%h 'bash -s' < $file $scriptargs 2>&1"
これはxargsのフラグと似ています-f
。-P
exec Executes an arbitrary command for each target host. The first of the pdsh remote arguments is the local command
to execute, followed by any further arguments. Some simple parameters are substitued on the command line,
including %h for the target hostname, %u for the remote username, and %n for the remote rank [0-n] (To get a
literal % use %%). For example, the following would duplicate using the ssh module to run hostname(1) across
the hosts foo[0-10]:
pdsh -R exec -w foo[0-10] ssh -x -l %u %h hostname
and this command line would run grep(1) in parallel across the files console.foo[0-10]:
pdsh -R exec -w foo[0-10] grep BUG console.%h
-f number
Set the maximum number of simultaneous remote commands to number. The default is 32.
プレフィックスが付いたコマンドの出力をダンプする場合HOSTNAME:
ここに例があります。
$ pdsh -R exec -w host1,host2 bash -c "ssh -o StrictHostKeyChecking=no -p 22 %u@%h 'bash -s' <<< 'echo Running script on %h with arguments: \${@}' arg1 arg2 arg3"
host1: Running script on host1 with arguments: arg1 arg2 arg3
host2: Running script on host2 with arguments: arg1 arg2 arg3