0

rsyslog を使用していて、アプリケーションからのアクションをログに記録したいと考えています。ロギングは正常に機能し、ログ ファイルは適切に作成されます。

見たいので、出力をフォーマットしましたprogramname

rsyslog.conf:

$template usermsg,"%TIMESTAMP% %HOSTNAME% %programname% \n"
$ActionFileDefaultTemplate usermsg

出力:

Oct 14 16:28:25 box #001

「電卓」である必要がありますが、私は常に#001を取得します。programname誰かがそれを修正する方法を知っていますか?

アプリケーションでロガーのインスタンスを作成します。

//ident = "電卓"

//facility= LOG_USER /* (1<<3) ランダムなユーザーレベル メッセージ */

openlog(ident.c_str(), 0, 施設);

4

1 に答える 1

1

大げさな推測でidentは、 はスコープが限定された C++ 文字列オブジェクトです。つまり、ローカル変数である可能性が最も高く、せいぜいc_str()一時的に有効なポインターです。

このポインターは、アプリケーションの実行中ずっと有効である必要があります。openlog はマニュアルでこれを明確にしています:

openlog() の呼び出しの引数 ident は、おそらくそのまま格納されます。したがって、それが指す文字列が変更された場合、syslog() は変更された文字列を先頭に追加し始める可能性があり、それが指す文字列が存在しなくなった場合、結果は未定義です。最も移植性が高いのは、文字列定数を使用することです。

gnu.org のマンページには次のように記載されています。

文字列ポインタ ident は、Syslog ルーチンによって内部的に保持されることに注意してください。ident が指すメモリを解放してはなりません。スコープを離れると変数の有効期間が終了することになるため、自動変数への参照を渡すことも危険です。ident 文字列を変更したい場合は、openlog を再度呼び出す必要があります。ident が指す文字列の上書きは、スレッドセーフではありません。

したがって、最も可能性が高いのは、文字列変数がスコープ外になり、ランダムな文字列へのポインターになってしまうこと#001です。

解決策は数​​多くありますが、いずれもc_str()アプリケーションの実行中に が指すデータが変更されないようにする必要があります。

于 2013-11-23T00:30:52.293 に答える