|
OPTION LOGPATH = だと、変数や式が使えないので、スクリプト開始時にすでに決定していなければいけません。 スクリプトの途中で何度か変更したいのですが、何か良い方法は無いでしょうか?
|
No.4242 2017/07/20(Thu) 10:15:28
|
☆ Re: ログファイルをスクリプトの途中で変更したい / stuncloud |
|
|
1. printによるロギングを諦めてロギング専用関数を作る 現実的な解だとこれでしょう 例:
procedure print2(log, path) print log fid = fopen(path, F_READ or F_WRITE) gettime() t = G_TIME_YY2 + "/" + G_TIME_MM2 + "/" + G_TIME_NN2 + " " + G_TIME_HH2 + ":" + G_TIME_NN2 fput(fid, t + " " + log) fclose(fid) fend
printしつつ指定パスにログを書くという内容ですね fopen()を使うとログファイルが肥大化した際に読み書き動作が遅くなるので大量のログを書く場合は別の手段を用いたほうが良いです
2. LOGPATHを書き換えて再実行 無理やりやるパターン 例:
textblock [option] endtextblock OPTION LOGPATH=C:\fuga.log
const LOG_HOGE = "C:\hoge.log" const LOG_FUGA = "C:\fuga.log"
print "ログ書き込み"
if readini("option", "OPTION LOGPATH", GET_UWSC_NAME) = LOG_HOGE then writeini("option", "OPTION LOGPATH", LOG_FUGA, GET_UWSC_NAME) poff(P_UWSC_REEXEC) endif
再実行後に別の処理をさせたい場合はPARAM_STRを使った分岐処理を入れる等の工夫が必要です その場合はP_UWSC_REEXECじゃなくてexec等で自身を再実行しましょう 書いといてなんですがこんな方法は全くオススメしません
|
No.4243 2017/07/20(Thu) 11:06:42
|
|
☆ Re: ログファイルをスクリプトの途中で変更したい / 森 |
|
|
stuncloudさん
超高速回答ありがとうございます!
> fopen()を使うとログファイルが肥大化した際に読み書き動作が遅くなるので大量のログを書く場合は別の手段を用いたほうが良いです そう、これがネックなんですよね。 正規のログファイルでも、肥大化が原因だと思うのですが途中から残っていない場合もあって、途中で切り替えてみたいと思ったわけです。
> 書いといてなんですがこんな方法は全くオススメしません 思わず、ほっこりと笑ってしまいました(*´▽`*) ちょっとカリカリしてきていたので、良いガス抜きをしてもらった感じです。
とりあえず、PRINTした行数は把握できているので、途中で別ファイルに退避することで対処しようと思います。 ありがとうございました。
|
No.4244 2017/07/20(Thu) 11:31:55
|
|
☆ Re: ログファイルをスクリプトの途中で変更したい / stuncloud |
|
|
> 正規のログファイルでも、肥大化が原因だと思うのですが途中から残っていない場合もあって
OPTION LOGLINESを超えた分かな?と思いましたがそれだと古いログから削除されるはずなのではて…?
> fopen()を使うとログファイルが肥大化した際に読み書き動作が遅くなるので大量のログを書く場合は別の手段を用いたほうが良いです
F_READ or F_WRITE だと一旦ファイルの内容を全部読み取って、書き出すときも全部まるっと書いてるんじゃないかと思ってるんですよね なのでファイルが大きくなるほど遅くなっちゃう 昔数日に及ぶ作業をさせつつログ取ってたら、恐ろしくパフォーマンスが落ちてひどい目にあいました… そこで別の手段が欲しくなるというわけです ログファイルなんかは追記したいだけなのでそういうことができるものを使いましょう
path = "sample.log" const ForAppending = 8 // 追記 const TristateUseDefault = -2 // システムデフォルト(sjisっぽい)で書く
with createoleobj("Scripting.FileSystemObject") with .OpenTextFile(path, ForAppending, TRUE, TristateUseDefault) .WriteLine("追記モードで書き込み") .Close() endwith endwith
方法は色々ありますがFSOを使ったサンプルを書いてみました 1行300文字*5万行のテキストファイルに対してfopenだと500ミリ秒くらいかかってましたがこれだと15ミリ秒くらいでした UTF8で書きたい!というような場合だとADODB.Streamあたりが良いかもですね
|
No.4245 2017/07/20(Thu) 14:11:10
|
|
☆ Re: ログファイルをスクリプトの途中で変更したい / satocha |
|
|
巨大なログに書き込むとなると、追記できる手段が必要だと思います。 思いつくのは <OLE使用> 1)FileSystemObjectの追記モード 2)ADODB.Stream <shell系> 3)doscmd("文字列 >> logfile") 4)powershell("文字列 >> logfile") <powershellコマンドレット> 5)out-fileコマンドレットの-appendオプション使用 6)そのものずばりのadd-Contentコマンドレット <.Net> 7)powershellでstreamwriteクラスを使う(filemod.appendで)
1はstuncloudさんが説明sしてくださったとおりです。ログ出力にutf-8が使えないことが難点でしょうか。OLEオブジェクトを使うなら、2でしょうか。
3,4は手軽ですが、エンコードが固定されること、出力文字列に改行や引用符が入ってくるとエスケープが大変、などが難点です。
6は書き出し中にreadもロックしてしまうようなので、ログには不向きかもしれません。
7はほかの手段ではできなかったeucでの書き込みにも対応しているので、UNIX系OSと共存するようなシステムでは有効だと思います。ただ、設定が大変そうで、詳しく調べていません。
そこで、5のout-fileで作ってみました。
msgbox( AppendToLog( powershell( "date" )+ logtext,"D:\LOG\log.txt" ) )
textblock logtext 改行やら引用符があるテキスト 改行やら"引用符"があるテキスト 改行やら'引用符'があるテキスト endtextblock function AppendToLog( text, log=Get_AppData_Dir+"\UWSC\UWSC.LOG", charset="unicode" ) src =replace(_ApprndToLog_ps1,"<TEXT>",text) src =replace(src,"<LOG>",log) src =replace(src,"<CHARSET>",charset) result =powershell(src)
textblock _ApprndToLog_ps1 $text =@" <TEXT> "@ $log ="<LOG>" $charset ="<CHARSET>" $PossibleChars ="unicode,utf7,utf8,utf32,ascii,bigendianunicode,default,oem" -split "," if ( $PossibleChars -contains $log ){ $charset =$log $log ="$ENV:APPDATA\UWSC\UWSC.LOG" } if ( $PossibleChars -notcontains $charset ){ charset="unicode" } $text|out-file -append -encoding $charset $log endtextblock fend
|
No.4247 2017/07/21(Fri) 08:31:11
|
|
☆ Re: ログファイルをスクリプトの途中で変更したい / 森 |
|
|
stuncloudさん、satochaさん ありがとうございます!
扱うのは、UTF-8です。 ログを動作中にチェックしたいからRead Lockはダメ 改行は入りませんが、引用符はシングルもダブルも大量にあります
なので、satochaさんに書いて頂いた 5)out-file を試してみます。 問題があれば、ADODB.Stream ですね。
今日は別の事をやっているので、テストできるのは週明け。 また結果報告します!
|
No.4248 2017/07/21(Fri) 09:20:33
|
|
☆ Re: ログファイルをスクリプトの途中で変更したい / 森 |
|
|
途中報告です。 out-file -append でやってみました。 satochaさんのコードをベースにギリギリまで切り詰めてみましたが、10行のログ出力だけで6秒掛かりました。 残念ながら実用的では無かったです。 行けそうな気がしていたのですが、実際にやってみないと分らないものですね・・・ 次は、ADODB.Stream で試してみます。
AppendToLog.uws --------------------------------- dim log_data[]="あんず","いちご","イチジク","オレンジ","かぼす","柿","キウイ","栗","グレープ","さくらんぼ" for text in log_data[] AppendToLog( text , "hoge.log") next
procedure AppendToLog( text, log_file ) print text src = "(Get-Date).ToString(<#DBL>yyyy/mm/dd hh:mm:ss<#DBL>) + <#DBL> " + text + "<#DBL> | out-file -Encoding UTF8 -append " + log_file powershell(src) fend
hoge.logの出力結果 --------------------------------- 2017/32/21 09:32:40 あんず 2017/32/21 09:32:41 いちご 2017/32/21 09:32:42 イチジク 2017/32/21 09:32:42 オレンジ 2017/32/21 09:32:43 かぼす 2017/32/21 09:32:43 柿 2017/32/21 09:32:44 キウイ 2017/32/21 09:32:45 栗 2017/32/21 09:32:45 グレープ 2017/32/21 09:32:46 さくらんぼ
|
No.4256 2017/07/21(Fri) 21:43:00
|
|
☆ Re: ログファイルをスクリプトの途中で変更したい / 森 |
|
|
実用速度になりました。 読めれば良いので、FSOのUTF-16でも問題ないと思いますが、ADODB.StreamだとUTF-8(ただしBOM付)で書き出せるので、今回の私のケースではADODB.Streamを採用することにしました。 速度的にはどちらも高速で満足です。 ちなみにOut-Fileは、Out-File自体の処理が遅いのではなく、PowerShell()での実行が遅いのかなという感じですね。 stuncloudさん、satochaさん、ありがとうございました。 --------------------------------------- dim log_data[]="あんず","いちご","イチジク","オレンジ","かぼす","柿","キウイ","栗","グレープ","さくらんぼ" for log_str in log_data[] log_print( log_str , "hoge.log") log_print2( log_str , "hoge2.log") next
// FSO(stuncloudさんのコードをベースにUnicodeに変更) procedure log_print(log_str , path) print log_str gettime() t = G_TIME_YY2 + "/" + G_TIME_MM2 + "/" + G_TIME_NN2 + " " + G_TIME_HH2 + ":" + G_TIME_NN2 + ":" + G_TIME_SS2 log_str = t + " " + log_str with createoleobj("Scripting.FileSystemObject") with .OpenTextFile(path, 8 , TRUE, -1 ) .WriteLine(log_str) .Close() endwith endwith fend
// ADODB.Stream(UTF-8 ただしBOM付) procedure log_print2(log_str , path) print log_str gettime() t = G_TIME_YY2 + "/" + G_TIME_MM2 + "/" + G_TIME_NN2 + " " + G_TIME_HH2 + ":" + G_TIME_NN2 + ":" + G_TIME_SS2 log_str = t + " " + log_str with createoleobj("ADODB.Stream") COM_ERR_IGN try .Mode = 16 // 読み取り/書き込みモード 排他しない .Type = 2 .Charset = "UTF-8" .Open .LoadFromFile (path) // logファイルが無い時、ここでエラーになる .Position = .Size // ポインタを終端へ finally .writeText(log_str , 1) .SaveToFile(path , 2) .Close endtry COM_ERR_RET EndWith fend
|
No.4257 2017/07/22(Sat) 11:20:19
|
|