たまに掃除は必要!熱暴走…

イメージ
 そんなに暑くないのに… 本日、午前中にオンラインで打合せをしていると、突然マシンがダウン。 一瞬、停電か?と思ったもののディスプレイの電源は入っている。 あれっ?と思い、すぐさまノートで打合せを継続。 その間に、再度マシンの電源を投入。 問題なく起動する。 でも、CPU温度がたまたま目に入り、95℃を超えて徐々に上昇していく。 105℃あたりで再度マシンダウン。 これは、熱暴走によるダウンの可能性が高い。 以前、CPUをRyzen7→9にした頃は、60℃〜70℃程度だった記憶がある。 本当はGW中にSSDの載せ替えを行う予定だったけれど、忙しくて先延ばしにしていた。 その時やっていれば、多分掃除もしただろうに…。 ということで、午後からマシンを解体し、掃除をすることに。 ケース本体のFANはホコリがかなり溜まっている。 GPUのFANは問題ない。 電源とCPU FANはひどい。 一旦、CPU FANを取り外し、きれいにする。ついでにCPUグリスも塗り直しセット。 動作確認すると、投入直後で40℃台。 そりゃ、熱暴走も起こすわけだ。 せっかくバラしたので、SSDの載せ替えを実施。 OSは500GBで、ユーザ領域(/home)は1TBを使用しているもののAIのmodelをいくつも落としていたり、DockerのImageが多種置いてあるため、結構容量を食っている。 今回、2TBのSSD( Hanye SSD ¥17,800- で入手済)を用意してあるので、 1TB→2TB, 500GB→1TBと玉突きで移動させることを計画していたので実施する。 本当は、ddコマンドで移すつもりだったのだけれど、3月にお客さんのところで使いそうだったので、 ORICOのクローン機能付SSDアダプタ を入手済。 裸族のSSD版ですね…。1万円程度の品です。 これに、新品のSSDとこれまでの1TBのSSDを差し込んでクローン開始。 そこそこ時間はかかるものの、放置でOK。 ただ、HanyeのSSDについているヒートシンクが引っかかるため、一旦取り外してクローン後取り付ける必要があった。 続いて、500GB→先程の1TBに書き込み。 ただ、1TB(samsungの980pro)が、先程のクローンでかなり熱くなっていたため、速度低下が激しい感じ。1TB→2TBよりも時間がかかった感じ。 ...

ログの整理 #3

PowerShellでは遅すぎて…

実際問題、ログからcsvに切り出すことは可能になったものの、10MBのログから200kb前後のcsvファイルを生成するのに前回のスクリプトだと約2時間かかるんですねぇ。
そりゃ、1レコードを生成するのに、ログオンIDで再度全部ログを舐めて、PCの名前とIPを拾っているわけで…。
単純に考えればO(n^2)というわけですね。
ログのローテーションというか上限を5MB(半分)にすれば、多分処理速度は1/4程度にまで下がるとは思われるけれど、120分が30分になって、ファイル数が倍なので実質1時間かかるわけで…。orz。

何が遅い?

実際、何に時間がかかっているのかを調べ始めたのだけれど、まずwhere-Objectが結構な時間を消費している。その後foreachで回す処理は激遅い。
結局、イベントログからオブジェクトとして扱っているのが、遅さの原因ぽい。

最適化しようにも、PowerShell自体の扱いに慣れていないので、とっても疲れるです。

他に良い方法は無いものだろうか?と思案し始めた時に、以前オライリーの本で見た記憶があったので、ちょいっと検索してみる。

方針変更!

perlのモジュールにW32::EventLogが有るじゃないですか。
早速、マニュアルを参考にテスト用のコードを書いてみる。
さすがに、サーバ上での作業は心配なので、VM上のWindows7にActivePerlを入れてテストすることに。

細かい仕様を決めようか、汎用的に作ろうかと迷いつつも、現状の作業をサックリ行えることを目的に作成した。約1日かけて、コーディング終了。前回までのスクリプトと同じ結果を返すようにするところで、少々苦労したわ。

なので、若干コードは汚い(perlなのでさらに汚いww)とは思うのだけれど、これが素晴らしい性能を発揮してくれた。

コードは以下全体を載せておくので、もし万が一使いたい人は、自己責任にてお願いします。

さて、実際に同じデータを食わせてみると、なっなんと、2時間かかっていた処理を1分以内に終えてくれる!!!

あぁ、これで今後のログの整理が快適になる。
1週間分、いや1ヶ月分まとめて処理だって怖くない!
あとは、コマンドラインでイベントログを引数として渡せば良い仕様にしたので、バッチでも動かせるし…。

もう少し、バグ取りなんかも必要かもしれないし、エラー時の処理なんかは、全くしていないレベルなので、暇な時にでもやろうとは思っている。

この手間は、大きな差を産んでくれる! 120倍速の処理完了〜。


use Win32::EventLog;
$Win32::EventLog::GetMessageText = 1;
$DEBUG=0;
sub make_time {
  my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = @_;
  return sprintf("%04d/%02d/%02d %02d:%02d:%02d",$year+1900,$mon+1,$mday,$hour,$min,$sec);
}
sub event_hash4624{
my($strings)=@_;
my @event=('SubjectUserSid','SubjectUserName'    ,'SubjectDomainName'      ,'SubjectLogonId',
  'TargetUserSid' ,'TargetUserName'     ,'TargetDomainName'         , 'TargetLogonId',
  'LogonType'     ,'LogonProcessName'   ,'AuthenticationPackageName','WorkstationName',
  'LogonGuid'     ,'TransmittedServices','LmPackageName'            ,'KeyLength',
  'ProcessId'     ,'ProcessName'        ,'IpAddress'                ,'IpPort');
my @list = split(/[\0]/, $strings);
my %h;
for(my $idx=0;$idx<$#event;$idx++){
$h{$event[$idx]}=$list[$idx];
}
return %h;
}
sub event_hash4663{
my($strings)=@_;
my @event=('SubjectUserSid','SubjectUserName','SubjectDomainName' ,'SubjectLogonId',
  'ObjectServer'  ,'ObjectType'     ,'ObjectName'        ,'HandleId',
  'AccessList'    ,'AccessMask'     ,'ProcessId'         ,'ProcessName');
my @list = split(/[\0]/, $strings);
my %h;
for(my $idx=0;$idx<$#event;$idx++){
$h{$event[$idx]}=$list[$idx];
}
return %h;
}
sub convert_acl{
my ($access_list)=@_;
my %acl = ('%%1537'=>"Delete"                 ,'%%1538'=>"Read_CONTROL"  ,'%%1539'=>"Write_DAC",
  '%%1540'=>"Write_OWNER"            ,'%%1541'=>"Synchronize"   ,'%%4416'=>"ReadData (or List Directory)",
  '%%4417'=>"WriteData (or Add File)",'%%4418'=>"AppendData (or AddSubdirectory or CreatePipeInstance)",
  '%%4419'=>"ReadEA"                 ,'%%4420'=>"WriteEA"       ,'%%4421'=>"ExecuteFile",
  '%%4422'=>"DeleteChild"            ,'%%4423'=>"ReadAttributes",'%%4424'=>"WriteAttributes");
$access_list =~ s/^\s*(.*?)\s*$/$1/;
if($acl{$access_list}){
return $acl{$access_list};
}else{
return "Other";
}
}
sub make_db_id {
my ($eventlogname,$event_id) = @_;
  my $handle = Win32::EventLog->new($eventlogname) or die "can't open event log.\n";
  $handle->GetNumber($recs) or die "Can't get number of EventLog records\n";
  $handle->GetOldest($base) or die "Can't get number of oldest EventLog record\n";

  my $x=0;
  while ($x < $recs) {
    $handle->Read(EVENTLOG_FORWARDS_READ|EVENTLOG_SEEK_READ,
                  $base+$x,
                  $hashRef) or die "Can't read EventLog entry #$x\n";
    if($hashRef->{EventID} eq $event_id){
%eventdata = event_hash4624($hashRef->{Strings});
$workpc    = $eventdata{'WorkstationName'}?$eventdata{'WorkstationName'}:"";
$logonname = $eventdata{'TargetUserName'}?$eventdata{'TargetUserName'}:"";
    $logonid   = $eventdata{'TargetLogonId'};
$logonip   = $eventdata{'IpAddress'}?$eventdata{'IpAddress'}:"";
      if(!($logonname =~ /\$/)){
        $db_id{$logonid}=$workpc . "," . $logonip;
}
    }
    $x++;
  }
return %db_id;
}
my $archivelogname = $ARGV[0];
my %id_list = make_db_id($archivelogname,"4624");
my $csvfilename;
$csvfilename = $archivelogname;
$csvfilename =~ s/\.evtx$/\.csv/;
$csvfilename =~ s/^.+\\//;
open(FH,">$csvfilename") or die("Can't open csv file\n");
print FH "日時,ユーザ名,ドメイン名,ログオンID,コンピュータ名,IPアドレス,ファイル名,操作,アプリケーション";
    my $event_id="4663";
  my $handle = Win32::EventLog->new($archivelogname) or die "can't open event log.\n";
  $handle->GetNumber($recs) or die "Can't get number of EventLog records\n";
  $handle->GetOldest($base) or die "Can't get number of oldest EventLog record\n";

  my $x=0;
  while ($x < $recs) {
    $handle->Read(EVENTLOG_FORWARDS_READ|EVENTLOG_SEEK_READ,
                  $base+$x,
                  $hashRef) or die "Can't read EventLog entry #$x\n";
    if($hashRef->{EventID} eq $event_id){
%eventdata = event_hash4663($hashRef->{Strings});
            $csv = make_time(localtime($hashRef->{'TimeGenerated'})) . ",";
            $csv .= $eventdata{'SubjectUserName'} . ",";
            $csv .= $eventdata{'SubjectDomainName'} . ",";
            $csv .= $eventdata{'SubjectLogonId'} . ",";
if($id_list{$eventdata{'SubjectLogonId'}}){
$csv .= $id_list{$eventdata{'SubjectLogonId'}} . ",";
}else{
$csv .= ",,";
}
            $csv .= $eventdata{'ObjectName'} . ",";
            $csv .= &convert_acl($eventdata{'AccessList'}) . ",";
            $csv .= $eventdata{'ProcessName'};
            print FH $csv."\n";
    }
    $x++;
  }
close(FH);

コメント

このブログの人気の投稿

Ubuntu24.04 でGUIが死んだ

VirtualBoxが異常

MEGAにも弱点があった?