labunix's blog

labunixのラボUnix

postgresql9.1のログをsyslogに出力。ただし、メッセージは英語で。

■postgresql9.1のログをsyslogに出力。ただし、メッセージは英語で。

$ psql -c "select version();" -F, -A 2>&1 | cat
パスワード: 
version
PostgreSQL 9.1.13 on x86_64-unknown-linux-gnu, compiled by gcc (Debian 4.7.2-5) 4.7.2, 64-bit
(1 行)

■デフォルトは標準エラー出力。syslogに変更。

$ grep "log_.*stderr" /etc/postgresql/9.1/main/postgresql.conf 
#log_destination = 'stderr'		# Valid values are combinations of

$ sudo -u postgres vim /etc/postgresql/9.1/main/postgresql.conf 
$  grep "log_.*syslog" /etc/postgresql/9.1/main/postgresql.conf
log_destination = 'syslog'

$ sudo -u postgres /etc/init.d/postgresql reload 

$ tail -f /var/log/syslog
Jul 14 22:31:31 vm-debian postgres[5379]: [1-1] 2014-07-14 22:31:31 JST LOG:  ????? "log_destination" ? "syslog" ????????

■結論から言うと、「lc_messages='C'」または「lc_messages='en.UTF-8'」で
 文字化けを防止する必要がある。

$ sudo -u postgres grep lc_messages /etc/postgresql/9.1/main/postgresql.conf 
lc_messages = 'C'
#lc_messages = 'ja_JP.UTF-8'			# locale for system error message
$ sudo /etc/init.d/postgresql reload
[ ok ] Reloading PostgreSQL 9.1 database server: main.

■この変な文字。エンコード情報も持っていないようだ。

$ grep -i syslog /etc/postgresql/9.1/main/postgresql.conf 
log_destination = 'syslog'
					# stderr, csvlog, syslog, and eventlog,
# These are relevant when logging to syslog:
#syslog_facility = 'LOCAL0'
#syslog_ident = 'postgres'
					# DO NOT USE without syslog or

$ sudo tail -1 /var/log/syslog | nkf --guess
ASCII (LF)

■syslogには日本語が使える。
 これはpostgresqlに問題があるようだ。

$ echo "日本語" | logger
$ sudo tail -1 /var/log/syslog
Jul 14 23:03:31 vm-debian labunix: 日本語

■psqlの標準エラー出力をとってみる。

$ psql -c "show now();" 2>&1 | xargs echo | logger
パスワード: 
$ sudo tail -2 /var/log/syslog
Jul 14 23:06:00 vm-debian postgres[6085]: [2-2] 2014-07-14 23:06:00 JST ステートメント:  show now();
Jul 14 23:06:00 vm-debian labunix: ERROR: (またはその近辺で構文エラー 行 1: show now(); ^

$ sudo tail -2 /var/log/syslog
$ psql -c "select now();" 2>&1 | xargs echo | logger
パスワード: 
Jul 14 23:07:33 vmx-rdebian labunix: now ------------------------------- 2014-07-14 23:07:33.053672+09 (1 行)

■syslog設定自体は特別なものは無い。

$ psql -c "select name,setting from pg_settings where name like '%syslog%' order by name;" 2>&1 | cat
パスワード: 
      name       | setting  
-----------------+----------
 syslog_facility | local0
 syslog_ident    | postgres
(2 行)

$ psql -c "select name,setting from pg_settings where setting like '%syslog%' order by name;" 2>&1 | cat
パスワード: 
      name       | setting 
-----------------+---------
 log_destination | syslog
(1 行)

■この中のどれを参照しているのだろうか。

$ psql -c "select name,setting from pg_settings where setting like '%ja%' order by name;" 2>&1 | cat
パスワード: 
    name     |   setting   
-------------+-------------
 lc_collate  | ja_JP.UTF-8
 lc_ctype    | ja_JP.UTF-8
 lc_messages | ja_JP.UTF-8
 lc_monetary | ja_JP.UTF-8
 lc_numeric  | ja_JP.UTF-8
 lc_time     | ja_JP.UTF-8
(6 行)

■なんとなく分かってきた。わざと間違える。

$ psql -c "select name,setting from pg_settings where settin like ''" 2>&1 | cat
パスワード: 
ERROR:  列"settin"は存在しません
行 1: select name,setting from pg_settings where settin like ''

$ sudo tail -2 /var/log/syslog                                                 ^
Jul 14 23:30:37 vmx-rdebian postgres[6833]: [2-1] 2014-07-14 23:30:37 JST ERROR:  列"settin"は存在しません(文字位置 44)
Jul 14 23:30:37 vmx-rdebian postgres[6833]: [2-2] 2014-07-14 23:30:37 JST ステートメント:  select name,setting from pg_settings where settin like ''

■pg_ctlコマンドが原因の様子

$ su - postgres
$ export PGDATA=/usr/lib/postgresql/9.1/bin
$ export PATH=$PATH:$PGDATA
$ pg_ctl -D /var/lib/postgresql/9.1/main reload
サーバにシグナルを送信しました

■小文字で環境変数と言うのも変だけど、設定しても有効にはならない。

$ export lc_messages="ja_JP.UTF-8"
$ sudo tail -1 /var/log/syslog
$ sudo /etc/init.d/postgresql reload[ ok ] Reloading PostgreSQL 9.1 database server: main.
Jul 15 00:55:21 vmx-rdebian postgres[6879]: [30-1] 2014-07-15 00:55:21 JST LOG:  SIGHUP?????????????????????????

■参照先はlc_messagesの様子

$ strings /usr/lib/postgresql/9.1/bin/pg_ctl | grep locale
setlocale
/usr/share/locale

$ ls -ld /usr/share/locale/ja/LC_MESSAGES/
drwxr-xr-x 2 root root 12288  7月 13 22:24 /usr/share/locale/ja/LC_MESSAGES/

■ちなみにsetlocale相当のlocalesはちゃんと「ja_JP.UTF-8」。

$ ls -ld /usr/share/locale/locale.alias 
lrwxrwxrwx 1 root root 17  7月  9 05:29 /usr/share/locale/locale.alias -> /etc/locale.alias
$ ls -l /etc/locale.alias 
-rw-r--r-- 1 root root 2570 12月 31  2012 /etc/locale.alias
$ grep ja /etc/locale.alias 
japanese	ja_JP.eucJP
japanese.euc	ja_JP.eucJP
ja_JP		ja_JP.eucJP
ja_JP.ujis	ja_JP.eucJP
japanese.sjis	ja_JP.SJIS

■lc_messagesを変更してみる。

$ sudo -u postgres grep lc_messages /etc/postgresql/9.1/main/postgresql.conf 
lc_messages = 'ja_JP.UTF-8'			# locale for system error message
$ sudo -u postgres vim /etc/postgresql/9.1/main/postgresql.conf
$ sudo -u postgres grep lc_messages /etc/postgresql/9.1/main/postgresql.conf 
lc_messages = 'C'
#lc_messages = 'ja_JP.UTF-8'			# locale for system error message
$ sudo /etc/init.d/postgresql reload
[ ok ] Reloading PostgreSQL 9.1 database server: main.
$ sudo tail -1 /var/log/syslog
Jul 15 00:26:49 vmx-rdebian postgres[6879]: [25-1] 2014-07-15 00:26:49 JST LOG:  parameter "lc_messages" changed to "C"

■起動後は変更出来ないパラメータなのが残念。

$ sudo -u postgres psql -c "set lc_messages='ja_JP.UTF-8'"
SET
$ sudo -u postgres psql -c "select name,setting from pg_settings where name = 'lc_messages'"
    name     | setting 
-------------+---------
 lc_messages | C
(1 行)

$ sudo -u postgres psql -c "set lc_messages to 'ja_JP.UTF-8'"
SET
$ sudo -u postgres psql -c "select name,setting from pg_settings where name = 'lc_messages'"
    name     | setting 
-------------+---------
 lc_messages | C
(1 行)

■postmasterはpostgresにリンクされている。
 そしてこちらもLC_MESSAGESを参照。

$ ls -l /usr/lib/postgresql/9.1/bin/postmaster 
lrwxrwxrwx 1 root root 8  4月 13 23:27 /usr/lib/postgresql/9.1/bin/postmaster -> postgres
$ strings /usr/lib/postgresql/9.1/bin/postgres | grep -i "lc_messages\|/usr/share/locale"
LC_MESSAGES
lc_messages
/usr/share/locale

■クライアントには「psql-9.1.mo」があるのに対して、
 サーバ用のLC_MESSAGES用のモジュールが無いのが原因かな。
 「pg_ctl-9.1.mo」があればいけそうな気がするけど、またの機会に。