キーボード修理

イメージ
前回 調子が悪くなったと書きましたが、部品が手配できて時間が取れたので直しました。 茶軸のスイッチを購入 Cherryの茶軸は 10個で1,399- ということで購入。 本当は1個で充分なんだけど、仕方なく残りは予備部品として保管。 作業手順 キーボードの裏側ネジを3箇所外します。 左右と中央の丸シールの下。 左右はパッドを貼っているので、少しめくって外します。 (あとで綺麗に戻るので心配なしです) ケーブルが出ている方は、スッと外れ、手前(下側)は、内部に爪が有るので、ピックやカード、マイナスドライバなどで少し隙間を開けるようにして広げれば外れます。 自分は親指の爪で空きました。 今回は「E」が調子悪いので、該当のピン2箇所をハンダ吸いで綺麗に取り除いて、裏側から引き抜いて完了。 基板にしっかりとどのキーかがプリントされているので分かりやすいですねぇ 入手した新品の茶軸を差し込んでハンダ付けします。 この時点で動作確認が可能になるので、直したキーとその周辺が正しく入力できるのをチェック。 問題なく、無事に動作しました。 最後にカバーを取り付けて完了! 残ったのは9個の茶軸…。 今回の費用 Cherryの茶軸10個セット :1,399- キーキャップ引き抜き工具 : 475-  ちなみに10個セットには、簡易引き抜きがついてきますが、ちゃんとしたもののほうが楽に作業できます。(昔買ったのに、どこかに行ってしまったので再購入)  ということで、1900円ほどで完治しました。  手間賃考えると買ったほうが安いかも(笑)

ログの整理 #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);

コメント

このブログの人気の投稿

WPS Officeで日本語入力ができない

VirtualBoxでUSBから起動

Ubuntu24.04 でGUIが死んだ