Hatena::ブログ(Diary)

(ひ)メモ このページをアンテナに追加 RSSフィード

2013-08-21 (Wed)

撮った写真と動画の管理とかバックアップとか

写真

デジカメメイン機、サブ機共にEye-Fiを使っていて、撮ったら再生モードで放っておけばEye-Fiが写真データをアップロードしてくれます。

Eye-Fiからアップロードされたデータは、拙作のDoumeki (百目鬼)が受けます。

Doumekiは自宅サーバーで動いていて、

  • ローカルのディスク
  • Picasa

に保存します。アップロードの開始/完了の通知はEye-Fiからのメール通知で、進捗の通知はDoumekiがXMPPで通知するようにしています。

どちらも保存する際には、EXIFから撮影日を調べてその年月日を名前とするフォルダを作ってそこに保存します。写真はフォルダ分けの整理が面倒極まりないのですが、自分の場合はこの撮影日フォルダ自動仕分けがすこぶる便利だと思っています。


2個所に保存するのはバックアップの意味もありますが、それに加えて、

写真を見るのはiPhoneiPadBest Albumを使ってPicasaにあるデータを参照し、デジカメプリント等でオリジナルデータがが欲しい場合は、自宅サーバーのディスクをSMBでMBAにマウントしてそこで選んでデータをコピーするといった使い分けもしています。

動画

動画はあまり撮らないのですが、データ数が少なくともデータ量が大きいので保存場所に困ります。

自分の場合は、SDカードが一杯になったら

  • データを吸い出して自宅サーバーの外付けHDDに保存
  • 新しくSDカードを買って、一杯になったSDカードはそのまま保管

しています。

SDカードを使いまわしていないのは、

SONYのHDR-PJ630Vなんですが、MBAで再生するのがめんどくて、再生方法は専らカメラをテレビに繋ぐかカメラのプロジェクター機能を使うかなので、古いのを見るのにSDカード入れ替えで済ませたいからです。


ローカルディスクが壊れた && 古いSDカード失くしちゃった…場合もありうるので、動画データは最後の砦バックアップとしてAWSのS3経由でGlacierにも保存しています。

データのコピーは、s3cmd syncを使ってローカルディスクをS3にcronで差分同期しています。S3にデータを保存するとそこそこお金がかかるので、S3の設定で即時Glacierに保存するようにしています。

2013-08-14 (Wed)

シェルスクリプトでハマった件→【募】ステキな回避方法

追記: 解答編を下の方に書きました!!!

追記: お題に不備があったので変更しました><

あとgistに一式置いたので簡単にテストできます!!

git clone https://gist.github.com/6232206.git oreno
cd oreno
./test.sh source_me.sh
...


シェルは GNU bash, version 4.1.5(1)-release です。

こんな source_me.sh と、

case $PATH in
  */oreno/bin*)
    : # do nothing
    ;;
  *)
    . orenorc
    LOADED_ORENO=1; export LOADED_ORENO
    ;;
esac

orenorc ってファイルがあって、

ORENO_HOME="/oreno"; export ORENO_HOME
PATH=$PATH:$ORENO_HOME/bin
 
# 無視してもいい警告
echo "trivial warning" >&2
 
# やばいエラー!
echo "critical error"  >&2

sourceするとこんな感じになる。

$ PATH=/bin:/usr/bin; . source_me.sh; echo $PATH
trivial warning
critical error
/oreno/bin:/bin:/usr/bin

で、critical errorは出力したいけど、trivial warningは無視したいので画面に出したくないとします。(orenorcは深淵な理由でいじれないとします)

ぱっと思いつくのは

case $PATH in
  */oreno/bin*)
    : # do nothing
    ;;
  *)
    . orenorc
    LOADED_ORENO=1; export LOADED_ORENO
    ;;
esac 2>&1 | grep -v trivial

とか

case $PATH in
  */oreno/bin*)
    : # do nothing
    ;;
  *)
    . orenorc  2>&1 | grep -v trivial
    LOADED_ORENO=1; export LOADED_ORENO
    ;;
esac

とかだと思うんですが、これを実行すると、

$ PATH=/bin:/usr/bin; . source_me.sh; echo $PATH
critical error
/bin:/usr/bin

こうなっちゃって、trivial warning は表示されないんだけどPATHがセットされない。


原因は、シェルスクリプト書いてて毎年1回は踏むワナなのでわりとすぐに気がついたんだけど、回避方法できるのにちょっと時間がかかった上にスマートじゃない気がするのでステキな回避法を思いついたかたは教えてください!!!!


解答編

原因は?

原因は、外部コマンドが絡むとサブシェルで実行されるからです。※コメント欄のfumiyasuさんの書き込みもあわせて参照してください。

bashの場合、

  • BASHPID
    • 現在の bash のプロセス ID に展開されます。 bash を再初期化しないサブシェルのような、いくつかの環境においては、 $$ と値が異なります。
  • BASH_SUBSHELL
    • サブシェルやサブシェル環境が作成されるたびに 1 ずつ増えます。 初期値は 0 です。
Man page of BASH

で観測できるのでやってみましょう。

case文全体でgrepしているスクリプト(gistのsource_me-ng1.sh)は、

echo_pid() { echo "$@ $$ $BASHPID $BASH_SUBSHELL"; }

echo_pid 1
case $PATH in
  */oreno/bin*)
    : # do nothing
    ;;
  *)
    echo_pid 2
    . orenorc
    echo_pid 3
    LOADED_ORENO=1; export LOADED_ORENO
    ;;
esac 2>&1 | grep -v trivial
echo_pid 4

こういう結果になります。

PID=27549
1 27549 27549 0
2 27549 27604 1
o 27549 27604 1 # ←これは orenorc の中でのです
3 27549 27604 1
4 27549 27549 0

$$は変わっていませんが、caseの中ではBASHPIDとBASH_SUBSHELLが変化しています。

次に . oreno をgrepしているスクリプト(gistのsource_me-ng2.sh)では、こうなります。

PID=27649
1 27649 27649 0
2 27649 27649 0
o 27649 27704 1
3 27649 27649 0
4 27649 27649 0

source_meの世界では変わっていませんが、orenorcの世界は別プロセスで実行されているのがわかります。

さて、

いただいた回避法の紹介コーナー

いちばんステキだと思ったのは、@ さんのこれ(一部抜粋、完全版はgistのsource_me-ok-satoh_fumiyasu.sh)です。

  *)
    . orenorc 2> >(grep -v trivial >&2)
    LOADED_ORENO=1; export LOADED_ORENO
    ;;

stderrをbash(限定)のプロセス置換に渡しています。自分はこの発想はなかったです!

同じくプロセス置換を使っているのが、@さんのこれ(file-source_me-ok-sechiro-sh)です。

exec 2> >(grep -v trivial >&2)
case $PATH in
  */oreno/bin*)
    : # do nothing
    ;;
  *)
    . orenorc
    LOADED_ORENO=1; export LOADED_ORENO
    ;;
esac

同じようにstderrをプロセス置換に渡してるんですが、それをexecでやっています。

常々、execにフィルタが書ければstdout,stderr全部にタイムスタンプつけるのが簡単になるのになぁと思ってたんですが、この手法を使えばできますね。

exec  > >(tai64n | tai64nlocal)
exec 2> >(tai64n | tai64nlocal)

bashのプロセス置換については、sechiro さんがまとめてくださっているのでそちらを参照するのがいいと思います。スバラシス。


で、自分が考えたのはこんなの(source_me-ok-hirose31.sh)です。

tmpf=$(mktemp)
exec 3>&2 2>$tmpf
case $PATH in
  */oreno/bin*)
    : # do nothing
    ;;
  *)
    . orenorc
    LOADED_ORENO=1; export LOADED_ORENO
    ;;
esac
exec 2>&3 3>&-
cat $tmpf | grep -v trivial
rm -f $tmpf

あとで復元するようにfd 2をdupして3を作り、2を一時ファイルに向けます。

case文が終わったら、fd 2を復元(3をdupして2にする)して、3はもう要らないので閉じます。あとは一時ファイルをgrepして消します。

@さんも同じような手法を提案していました。


最後は@さん提案のmkfifoを使う方法です。こんなスクリプト(source_me-ok-m2ym.sh)になるかと思います。

fifo=$(mktemp -u)
mkfifo $fifo
grep -v trivial <$fifo &
exec 3>&2 2>$fifo
rm -f $fifo
case $PATH in
  */oreno/bin*)
    : # do nothing
    ;;
  *)
    . orenorc
    LOADED_ORENO=1; export LOADED_ORENO
    ;;
esac
exec 2>&3 3>&-

自分の環境では exec の前に grep しないと exec がブロックして止まっちゃったので気をつけましょう。

いずれもfd 2をファイルやFIFOに向ける手法です。@ さんはコメント欄でファイル的なものを作らない方法を提案していましたが、残念ながらうまく動きませんでした。ファイル的なものを使わない方が消し忘れがなくてよいので、うまくできる書き方があったら是非教えてください><

回答スクリプトも含め gist (https://gist.github.com/hirose31/6232206) に置きましたので興味ある方はぞうぞ!

最後に、回答くださった皆様、ありがとうございました!!


参考ページ

2013-08-08 (Thu)

補助グループ権限もつけてくれるsetuidgidのようなもの

daemontoolsのsetuidgidは補助グループ(supplementary groups)権限をつけてくれないのですが、どうしてもつけたい時もあります。あるはずです。

いくつか検討したのでそのメモです。

自分で書く!

結局この方法にしました。

daemontools-encore の setuidgid を使う

これの setuidgid は -s オプションで補助グループ権限をつけてくれるようです。

daemontools の setuidgid をいじる

数行足すだけです。

--- setuidgid.c 2001-07-13 01:49:49.000000000 +0900
+++ setuidgidgroups.c   2012-11-20 20:21:21.574829697 +0900
@@ -3,6 +3,7 @@
 #include "prot.h"
 #include "strerr.h"
 #include "pathexec.h"
+#include <grp.h>

 #define FATAL "setuidgid: fatal: "

@@ -21,6 +22,8 @@

   if (prot_gid(pw->pw_gid) == -1)
     strerr_die2sys(111,FATAL,"unable to setgid: ");
+  if (initgroups(account, pw->pw_gid) == -1)
+    strerr_die2sys(111,FATAL,"unable to initgroups: ");
   if (prot_uid(pw->pw_uid) == -1)
     strerr_die2sys(111,FATAL,"unable to setuid: ");

su を使う

suはexecじゃなくてforkするので setuidgid の代わりとしては使えません。

$ cat /tmp/p.sh
#!/bin/sh
echo $$

# sh -c 'echo $$ && exec su nobody -c "/tmp/p.sh"'
21231
21232

runuser を使う

runuserはRHEL系のcoreutilsに含まれているコマンドのようです。

これも fork するのでダメです。

# sh -c 'echo $$ && exec runuser nobody -c "/tmp/p.sh"'
21198
21199

sudo を使う

バージョン(?)によって挙動が違うのでイマイチです。。

CentOS 6.2
# cat /etc/redhat-release
CentOS release 6.2 (Final)

# sudo -V | head -n 1
Sudo version 1.7.4p5

# sh -c 'echo $$ && exec sudo -u nobody /tmp/p.sh'
21253
21255
Ubuntu 10.04
# lsb_release -ir
Distributor ID: Ubuntu
Release:        10.04

# sudo -V | head -n 1
Sudo version 1.7.2p1

# sh -c 'echo $$ && exec sudo -u nobody /tmp/p.sh'
29309
29309
Ubuntu 12.04
# lsb_release -ir
Distributor ID: Ubuntu
Release:        12.04

# sudo -V | head -n 1
Sudo version 1.8.3p1

# sh -c 'echo $$ && exec sudo -u nobody /tmp/p.sh'
2206
2207

runit の chpst を使う

できそうな気がしますが試してません。

2013-08-07 (Wed)

How to defend SSL/TLS servers against BEAST, CRIME and BREACH attack for Nginx

The information presented herein is without any guarantees and I’ll take no responsibility if any harm happens to you or your users. If you find any factual problems, please reach out to me(@) immediately and I will fix it ASAP.

http {
  server {
    listen  80;
    listen 443 ssl;
    server_name example.com;

    # BEAST: dont's use CBC
    ssl_protocols SSLv3 TLSv1;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:RC4-SHA;
    ssl_prefer_server_ciphers on;

    # CRIME: disble TLSv1 compression: use nginx 1.0.9+/1.1.6+ w/ OpenSSL 1.0.0+ or 1.2.2+/1.3.2+ w/ older OpenSSL

    gzip on;

    location = /foo {
      # BREACH: disable HTTP compression
      if ($ssl_protocol) { gzip off; }
    }

    location / {
      # BREACH: disable HTTP compression
      if ($ssl_protocol) { gzip off; }
    }
  }
}

see also

2003 | 11 | 12 |
2004 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 10 | 11 | 12 |
2005 | 01 | 02 | 03 | 05 | 08 | 09 | 10 | 11 | 12 |
2006 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 12 |
2012 | 01 | 02 | 03 | 06 | 08 | 10 | 11 | 12 |
2013 | 01 | 02 | 03 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2014 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 10 |
2015 | 01 | 02 | 07 | 10 |
2016 | 01 | 05 | 10 | 12 |
2017 | 07 |
2018 | 05 |