てきとうなメモ

本の感想とか技術メモとか

--no-preserve-rootオプション

サーバ業者が" rm -rf / "で全サーバを誤消去、復旧法をQ&Aサイトに尋ねる。実は書籍執筆のための「引っ掛け問題」 - Engadget Japanese

種明かしをすると、現在の UNIX(Linux)システムでは管理者権限で "rm -rf / " を実行しても警告メッセージが表示され、すぐにはファイルを削除しないようになっています。そのうえで、本当に削除をするなら"-no preserve"オプションを付けて実行することになっています。このことをどれだけのユーザーが知っているか、マルサラは試したわけです。このとき、質問へのアクセス数は述べ14万に達していましたが、このことを指摘する人はほとんどいませんでした。

--no-preserve-rootオプションのことだと思うけども、そういえばそんなオプションあったなあ。

これいつからなんだろと調べてみるとcoreutilsChangelogを調べると結構古い

2003-11-09 Jim Meyering

* Use automake-1.7.9. Regenerate dependent files.

* src/rm.c: Support new options: --preserve-root and --no-preserve-root.
* src/chown.c: Likewise.

http://git.savannah.gnu.org/cgit/coreutils.git/tree/ChangeLog-2005#n7384

2003-12-20 Jim Meyering

* Version 5.1.0.

http://git.savannah.gnu.org/cgit/coreutils.git/tree/ChangeLog-2005#n7238

どうも2003年末の5.1.0かららしい。

ちなみにrmだけでなくchownやchgrpも--no-preserve-rootオプションがある。所有者/グループを全部変えられると動かなくなるしなあ

suやsudoにおけるPATH

suとかsudoとかrootになる方法はいくつかあるけど、/usr/local/binにパスが通っていないことがあった。
で、なんでかなと。

centos7の環境で確認すると以下のようになる。

$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/vagrant/.local/bin:/home/vagrant/bin
$ su
# echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/vagrant/.local/bin:/home/vagrant/bin
# exit
$ su -
# echo $PATH
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
# exit
$ sudo -s
# echo $PATH
/sbin:/bin:/usr/sbin:/usr/bin
# exit
$ sudo -i
# echo $PATH
/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
# exit

結構違う。

まず、suした時はsuを実行したユーザのPATHを引き継ぐ。

su -した時は以下manにあるように

-, -l, --login
シェルをログインシェルにする。すなわち以下のような取り扱いをする: すべての環境変数を解除する。その上で `TERM'、 `HOME'、 `SHELL' を前述 のように設定し、
`USER'、 `LOGNAME' (スーパーユーザーであっても)を同 じく前述のように設定する。続いて `PATH' をコンパイル時のデフォルト値に 設定する。ディレクトリを user
のホームディレクトリに変更する。シェル名の前に `-' を付加し、シェルに ログイン時のスタートアップファイルを読ませる。

コンパイル時のデフォルトのPATH+シェルのログイン時のスタートアップファイルになる。

コンパイル時のデフォルトはutil-linux(centos7のsuを含む)のソースコードを見ると

// util-linux-2.23.2/login-utils/su-common.c 
  if (pw->pw_uid)
    r = logindefs_setenv("PATH", "ENV_PATH", _PATH_DEFPATH);

  else if ((r = logindefs_setenv("PATH", "ENV_ROOTPATH", NULL)) != 0)
    r = logindefs_setenv("PATH", "ENV_SUPATH", _PATH_DEFPATH_ROOT);

となっていて

// util-linux-2.23.2/include/pathnames.h
#undef _PATH_DEFPATH
#define _PATH_DEFPATH           "/usr/local/bin:/bin:/usr/bin"

#undef _PATH_DEFPATH_ROOT
#define _PATH_DEFPATH_ROOT      "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"

となっているので

/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

さらに、/root/.bash_profileに

PATH=$PATH:$HOME/bin

が書かれているので/root/binが追加されている。

sudoした場合はそもそもデフォルトでsecure_pathの設定がしているので、

# /etc/sudoers
Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin

上記のパスがベースになり、シェルを普通に実行する場合(-s)とログインシェルとして実行する場合(-i)との違いがある。

ログインシェルだと/etc/profileも読み込まれるので

# /etc/profile
# Path manipulation
if [ "$EUID" = "0" ]; then
    pathmunge /usr/sbin
    pathmunge /usr/local/sbin
else
    pathmunge /usr/local/sbin after
    pathmunge /usr/sbin after
fi

が実行されて/usr/local/sbinが付加される。

PostgreSQLのbyteaカラムが\xXXXXXXと表示される

$ psql test
test=> create table t(b bytea);
CREATE TABLE
test=> insert into t(b) values('foo');
INSERT 0 1
test=> select * from t;
    b     
----------
 \x666f6f
(1 行)

'foo'を挿入すると'\x666f6f'と16進表示される。

PostgreSQL 9.0の仕様変更っぽい。

byteaの出力はデフォルトで16進数書式になりました。(Peter Eisentraut)

互換性が必要ならばbytea_outputサーバパラメータを使用して伝統的な出力書式を選択することができます。

リリース9.0

これを回避するためにはencode関数を利用するか

test=> select encode(b, 'escape') from t;
 encode 
--------
 foo
(1 行)

サーバの設定(postgresql.conf)を変更する

bytea_output (enum)
bytea型の値の出力形式を設定します。 有効な値はhex(デフォルト)、およびescape(PostgreSQLの伝統的な書式)です。 より詳細は項8.4を参照してください。 bytea型は常にこの設定に係わらず、入力時に双方の書式を受け付けます。

クライアント接続デフォルト
bytea_output = 'escape'

perlでパイプを使ってコマンドの入出力をopenした時のエラー処理

closeした時にエラーが返るのか

open(my $f, 'ls hoge |');
close $f or die $! ? "error on closing pipe" : "exit status = $?";
$ perl sample.pl
ls: hoge: No such file or directory
exit status = 256 at sample.pl line 2.

closeが失敗するのはパイプのcloseに失敗した場合とコマンドが失敗した場合とがあるが、$!が0かどうかで判別がつく。コマンドが失敗すると0になる。

$ perldoc -f close
...
            If the filehandle came from a piped open, "close" returns false if
            one of the other syscalls involved fails or if its program exits
            with non-zero status. If the only problem was that the program
            exited non-zero, $! will be set to 0. 

あと、$?はコマンドの戻り値が入っているがシェルの$?とは異なる

$ perldoc perlvar
...
    $CHILD_ERROR
    $?
...
            This is just the 16-bit status word returned by the
            traditional Unix "wait()" system call (or else is made up to look
            like it). Thus, the exit value of the subprocess is really ("$? >>
            8"), and "$? & 127" gives which signal, if any, the process died
            from, and "$? & 128" reports whether there was a core dump.

上位8ビットがコマンドの戻り値を表し、次の1ビットがコアダンプがあるかどうか、残り7ビットがどのシグナルで死んだか入っている。

ので、今回はコマンドの戻り値は1である

CentOS7でのscreenのタイトルとか端末のタイトル

CentOS7でちょっと便利になっていたのでどうなっているのかなと。

デフォルトの状態で以下のようになっている

screen screenのタイトル 端末のタイトル
× ユーザ@ホスト名:作業ディレクトリ
ユーザ@ホスト名:作業ディレクトリ [screen ウィンドウ番号: ユーザ@ホスト名:作業ディレクトリ]

まず、端末の機能として、

ESC]0;端末のタイトルBEL

を出力すると、これをタイトルとして表示することができる(ESCは0x1b、BELは0x07)。ちなみに「ESC]0;」の0の部分は1や2でも大丈夫なようだ。CentOS7では/etc/bashrcの中で環境変数のPROMPT_COMMANDを指定することでタイトルを「ユーザ名@ホスト名:作業ディレクトリ」にしている

PROMPT_COMMAND='printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"'

次にscreenのウィンドウタイトルの方だが、screenには

ESCkウィンドウのタイトルESC\

が出力されるとこれをウィンドウのタイトルとして設定する機能があり、CentOS7ではこれを利用している。

screenを実行した場合、環境変数TERMがscreenに設定されるため、/etc/bashrcでPROMPT_COMMANDが以下に設定される。

PROMPT_COMMAND='printf "\033k%s@%s:%s\033\\" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"'

そのため、screenのウィンドウタイトルも「ユーザ名@ホスト名:作業ディレクトリ」になる。

最後に、screen実行時の端末のタイトルは/etc/screenrcで指定している。

screenにはハードステータス行を設定するコマンドがあり、以下でハードステータス行を指定できる。

hardstatus string ハードステータス行

ハードステータス行はscreenの機能ではなく端末の機能で、実行中のプロセス情報などを表示させるためのものである。端末の実装によって1番下の行に表示したりする。

CentOS7の/etc/screenrcでは以下のように設定されている

hardstatus string "[screen %n%?: %t%?] %h"

このコマンドのハードステータス行の部分には%を使ったエスケープシーケンスが利用できる。今回は以下のものが利用されている。

%n ウィンドウ番号
%t ウィンドウタイトル
%h ハードステータス行
%? 次の%?までのエスケープの中身が存在すれば%?〜%?を表示し、なければ何も表示しない

ハードステータス行はまだ設定されていないので空、ウィンドウタイトルは「ユーザ@ホスト名:作業ディレクトリ」になっているので「[screen ウィンドウ番号: ユーザ@ホスト名:作業ディレクトリ] 」になる。

ハードステータス行がなぜ端末のタイトルに表示されているのかは、同じく/etc/screenrcで設定されている。screenにはtermcap/terminfoの設定を修正するコマンドがあり、以下でそれを指定できる。

termcapinfo term terminal-tweaks

termcapやterminfoは端末を操作するためのライブラリ/設定データベースであり、端末上である操作をしたい場合、端末に対してどのように指定すれば良いかを記述することができる。

端末の種類ごとに設定を記述することができ、termで端末を絞りこみ、terminal-tweaksでtermcap/terminfoの設定を記述する。CentOS7の/etc/screenrcには、以下の記述がある。

termcapinfo xterm|xterm-* 'hs:ts=\E]2;:fs=\007:ds=\E]2;screen\007'

これはxtermやxterm-*の端末に対するエントリを「'hs:ts=\E]2;:fs=\007:ds=\E]2;screen\007'」のように修正する。

termcap/terminfoのエントリは各定義をコロンで分割していて、各定義は「capability[=値]」という形式で記述される。今回利用されているcapabilityは以下のものである。

hs ハードステータス行を持つ
ts ハードステータス行を開始する時のコマンド
fs ハードステータス行から戻る時のコマンド
ds ハードステータス行が無効する時のコマンド

よって、今回は

  • ハードステータス行を持つ
  • ハードステータス行の表示するときには「\E]2;」を使用
  • ハードステータス行から戻るときには「\007」を使用
  • ハードステータス行を無効にする時には「\E]2;screen\007」を使用

というエントリになっている。ここで\EはESCを意味する。よってscreenはハードステータス行を表示する際に、

ESC]2;ハードステータス行BEL

と出力し、端末のタイトルにハードステータス行が表示されることになる。

ハードステータス行を無効にした時の出力を確認するためには、

C-a : hardstatus alwaysignore

を実行する。そうするとタイトルが

screen

と表示される

nullさんとか名前の多様性

アメリカ人のNullさん、名前のせいでウェブサイトに登録できない事案が発生 : ギズモード・ジャパン

今時そんな実装なのはどうなんだろうと思ったが、原文にはいろいろおもしろい例が載っていた。

Some individuals only have a single name, not a forename and surname. Others have surnames that are just one letter. Problems with such names have been reported before. Consider also the experiences of Janice Keihanaikukauakahihulihe'ekahaunaele, a Hawaiian woman who complained that state ID cards should allow citizens to display surnames even as long as hers – which is 36 characters in total. In the end, government computer systems were updated to have greater flexibility in this area.

姓名がなく1つの名前だけだったら、姓が1文字だったら、逆に36文字だったら。。。1文字の例と36文字の例は以前報道されたものらしい。

また、日本で暮らすMcKenzieさんも姓の部分が長すぎて入力エラーになったとか。欧米では珍しくなくても、日本だと平仮名or漢字で5文字ぐらいあれば十分そうではある。

“Four characters in a Japanese name is very rare. McKenzie is eight, so for printed forms it’ll often be the case that there’s literally not enough space to put my name,” he says.
“Computer systems are often designed with these forms in mind. Every year when I go to file my taxes, I file them as ‘McKenzie P’ because that’s the amount of space they have.”

そもそも1つの名前しかない場合やミドルネームを考えると姓名を別のフィールドにしない方が良いのかも知れない。

確かに国際化していろんな国の人がいろんな国に行くようになるとシステムのエッジケースも十分に考えないといけなくなりそうだな。

紙のコミックとKindleコミックで発売日が同じもの 2016年05月分

i・ショウジョ+ カラー版 7 (ジャンプコミックスDIGITAL)

i・ショウジョ+ カラー版 7 (ジャンプコミックスDIGITAL)

ものの歩 3 (ジャンプコミックスDIGITAL)

ものの歩 3 (ジャンプコミックスDIGITAL)

れっつ!ハイキュー!? 3 (ジャンプコミックスDIGITAL)

れっつ!ハイキュー!? 3 (ジャンプコミックスDIGITAL)

ハイキュー!! 21 (ジャンプコミックスDIGITAL)

ハイキュー!! 21 (ジャンプコミックスDIGITAL)

ブラッククローバー 6 (ジャンプコミックスDIGITAL)

ブラッククローバー 6 (ジャンプコミックスDIGITAL)

食戟のソーマ 18 (ジャンプコミックスDIGITAL)

食戟のソーマ 18 (ジャンプコミックスDIGITAL)

天神―TENJIN― 3 (ジャンプコミックスDIGITAL)

天神―TENJIN― 3 (ジャンプコミックスDIGITAL)

BUNGO―ブンゴ― 5 (ヤングジャンプコミックスDIGITAL)

BUNGO―ブンゴ― 5 (ヤングジャンプコミックスDIGITAL)

てらほくん (ヤングジャンプコミックスDIGITAL)

てらほくん (ヤングジャンプコミックスDIGITAL)

ひゃくにちかん!! 1 (ヤングジャンプコミックスDIGITAL)

ひゃくにちかん!! 1 (ヤングジャンプコミックスDIGITAL)

もぐささん 10 (ヤングジャンプコミックスDIGITAL)

もぐささん 10 (ヤングジャンプコミックスDIGITAL)

もののがたり 4 (ヤングジャンプコミックスDIGITAL)

もののがたり 4 (ヤングジャンプコミックスDIGITAL)

グラビアトリ 3 (ヤングジャンプコミックスDIGITAL)

グラビアトリ 3 (ヤングジャンプコミックスDIGITAL)

元ヤン 4 (ヤングジャンプコミックスDIGITAL)

元ヤン 4 (ヤングジャンプコミックスDIGITAL)

マドンナはガラスケースの中(2) (リュエルコミックス)

マドンナはガラスケースの中(2) (リュエルコミックス)

アナグラアメリ 1 (マーガレットコミックスDIGITAL)

アナグラアメリ 1 (マーガレットコミックスDIGITAL)

スイートソロウ 3 (マーガレットコミックスDIGITAL)

スイートソロウ 3 (マーガレットコミックスDIGITAL)

ハル×キヨ 9 (マーガレットコミックスDIGITAL)

ハル×キヨ 9 (マーガレットコミックスDIGITAL)

雛鳥のワルツ 5 (マーガレットコミックスDIGITAL)

雛鳥のワルツ 5 (マーガレットコミックスDIGITAL)

彼と恋なんて 2 (マーガレットコミックスDIGITAL)

彼と恋なんて 2 (マーガレットコミックスDIGITAL)