page_adsence

2011年1月27日木曜日

crontabの書き方

いつもお世話になっているcron による定期実行。「cron なんて簡単だよ」っと思ってる方は結構多いのではないだろうか。いや、実際に cron はわかりやすいプログラムだし、そんなに難しいものではない。だが、意外と覚えることが多く(メモっておけば覚える必要なんてこれっぽっちもないんだが)、自分の思うような動作をしてくれなかったりすることもあるので、ちょっとだけ cron について真剣に勉強してみることにした。まず、基本中の基本として、cron の設定ファイルは、/etc/crontab に記述されている。さらには、/etc/cron.daily/、/etc/cron.weekly/、/etc/cron.monthly/ 以下に格納された設定ファイルを1日1回、週に1回、月に1回と実行してくれるのはすでに周知のことだろう。

まず、/etc/crontab を見てみる。筆者のLANDISKでは、デフォルトでは以下のように記述されている。まず、/etc/cron.daily と、/etc/cron.weekly と /etc/cron.monthly 以下のスクリプトを実行するということは、crontab を見慣れた方ならば一目瞭然だが、test だの、run-parts だの、/usr/sbin/anacron だのは実際になにをやっているのだろうか? まず、test -x という部分を見てみる。これは、「ファイルが存在すれば実行する」ということを意味している。test -x /usr/bin/anacron で、/usr/sbin/anacronが存在するかどうかをチェックし、存在しなければを表すのが「|| 」の記号になる。run-parts はコマンドを表し、ディレクトリ内にあるスクリプトを実行するコマンドのことである。つまり、/etc/cron.daily/ 以下にあるスクリプトが実行できるようになる。結論としてこの1行は「/usr/sbin/anacronがあるかどうかチェックし、なければ、run- parts コマンドを実行しろ」ということを表している。実際に、筆者の環境では、anacron はインストールされていないので run-parts コマンドが実行されることになる。--report というオプションは、verbose みたいなものだが、スクリプトの名前のみが出力されると man には書いてあった。

landisk:~# cat /etc/crontab

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user command
17 * * * * root run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || run-parts --report /etc/cron.daily
47 6 * * 7 root test -x /usr/sbin/anacron || run-parts --report /etc/cron.weekly
52 6 1 * * root test -x /usr/sbin/anacron || run-parts --report /etc/cron.monthly

次に、左から数えて5番目のフィールドまで説明する。* (アスタリスク)があったり、数字があったりする箇所だ。率直に左からいうと、「分(minutes)・時(hour)・日(day)・月(month)・週(week)」という順番になっている。* を指定した場合は、全ての有効な値が設定されたことになります。

 分(minutes) 0-59 の間で指定する
 時(hour) 0-23 の間で指定する
 日(day) 1-31 の間で指定する
 月(month) 1-12 もしくは、名前
 週(week) 0-7 もしくは、名前。0 と 7 は日曜日。


例1) 毎朝6時25分に hoge.sh を実行する

25 6 * * * /usr/local/bin/hoge.sh

例2) 3時間ごとにhoge.shを実行する。

0 */3 * * * /usr/local/bin/hoge.sh

例3) 12月24日0時0分、クリスマスイブに hoge.sh を実行。なにが起きるんだろう。

0 0 24 12 * /usr/local/bin/hoge.sh

例4) 8時から17時の間、2時間ごとに、hoge.sh を実行する

0 8-17/2 * * * /usr/local/bin/hoge.sh

例5)毎月2日、12日、22日の12時にhoge.sh を実行する

00 12 2,12,22 * * /usr/local/bin/hoge.sh


■環境変数・シェル変数の定義

/etc/crontab の先頭には、以下のような環境変数やシェル変数を記述しておきます。cron はデフォルトでは、/etc/crontab の所有者(つまり、root )にメールを送信し、その実行結果を報告します。特定の宛先にメールを送信する場合は、MAILTO でアドレスを指定します。「MAILTO=""」のように空白を指定した場合は、誰にもメールを送信しなくなります。その他、環境変数 PATH を記述しておくことで、コマンドを絶対パスで記述する必要がなくなります。

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root




     crontab コマンド
 
/etc/crontab は直接編集するのではなく、crontab -e コマンドによって編集するのがBEST(当然?)とされています。筆者のようななんちゃってリナクサーは、直接 vi で編集してしまうのですが、作法としては良い事ではなさそうな感じです。まぁ、でも編集してはいけないということではなく、大まかな指定では、/etc /cron.{hourly,daily,weekly] で指定し、より細かく制御したい場合は、/etc/crontab もしくは、crontab -e を使ったほうが管理の面でも楽なことは確かです。あるいは、/etc/cron.d/ 以下にスクリプトを置くという手もありますね。/etc/crontab と crontab -e では、crontab が保存される場所が異なるので、編集するならどちらか片方に統一しておいた方が良いと思います(どちらか片方のファイルを見ればいいだけなので)。 crontab -e コマンドを使うと、root のみならず、一般ユーザも定期的な実行を行うことができます。その場合、/var/spool/cron/user に個別に設定が保存され、root の場合は、/var/spool/cron/root に保存されるようになる。cron の場合、設定ファイルを保存した時点で、cron が自動的に変更を検知するため、cron デーモンの再起動は必要ありません。/etc/hosts.allow などのように、保存した時点で設定が反映されます。

crontab のオプションを以下に記述します。書式に関しては、/etc/crontab と同様である。ユーザフィールド(/etc/crontab では root となっている箇所)は自分のcrontab なので省略することができる(/etc/crontab でも省略できるが)。

 -e crontabを編集する。
 -l 登録されているcrontabを表示する。
 -r 登録されているcrontab を削除する
 -u ユーザ名 設定するcrontabのユーザ名を指定する




     メール送信設定
 
cron は、 /etc/crontab に記述された処理を 指定したユーザ宛にその実行結果を送信します。これはとてもありがたい機能ですが、時として非常にうざったい機能にもなります。Logwatch のように 稼動しているサービス一覧のログを取得し、一通のメールにまとめて送信してくれるならまだしも、ひとつひとつのシェルスクリプトに対して個別にメールを送られたのではたまったものじゃありません。なので、メールを送信してもいいジョブと、送信する必要のないジョブを明確にきりわけておく必要があるでしょう。

①----
標準出力、標準エラー出力とも捨てる設定です。つまり、メールは送信しないし、ファイルにも出力しない、スクリプトを実行した記録はどこにも残らないという意味なります。

②----
標準出力を捨て、標準エラー出力をメールで送信する設定です。エラーになった処理だけを知らせてくれるので場合によっては①よりも効率が良いといえます。

③----
メール送信はしないが、/var/log/origin.log に標準出力と標準エラー出力を残すという意味になる。メールで通知を受け取るほど重要度が高くないが、一応ログには残しておきたい場合には、この方法は有効でしょう。

25 6 * * * root test -x /usr/sbin/anacron || run-parts --report /etc/cron.daily
47 6 * * 7 root test -x /usr/sbin/anacron || run-parts --report /etc/cron.weekly
52 6 1 * * root test -x /usr/sbin/anacron || run-parts --report /etc/cron.monthly

05 5 * * * root /usr/local/bin/hoge.sh > /dev/null 2>&1 ----------------①
05 5 * * * root /usr/local/bin/hoge.sh 1> /dev/null 2> /dev/null ---------①
05 5 * * * root /usr/local/bin/hoge.sh 1> /dev/null ----------------------②
05 5 * * * root (/usr/local/bin/tames.sh > /var/log/origin.lo 2>&1) > /dev/null --③

MySQLのDATE_FORMAT関数はかなり便利

集計をするにあたって、日別や月別に集計したい場合、とりあえずMySQLでは期間内のデータを全件取得してから、PHPで整形してたんですが、MySQLでいい感じにできるみたいです。

(※日時を格納しているフィールド「time」の型はdatetimeでもcharでもいける)

//【年別に集計】
SELECT id, DATE_FORMAT(time,'%Y年') as time1 FROM table1 GROUP BY time1

//【月別に集計】
SELECT id, DATE_FORMAT(time,'%Y年%m月') as time2 FROM table1 GROUP BY time2

//【日別に集計】
SELECT id, DATE_FORMAT(time,'%Y年%m月%d日') as time3 FROM table1 GROUP BY time3

参考
http://ma-bank.com/item/604

2011年1月26日水曜日

phpで配列の中に含まれるマルチバイトのテキストを一気に文字コード変換する関数

今までforeachとかでまわしていちいち変換してたけど、そんなの全く不要だった…。

mb_convert_variables

マジで便利だ。

2011年1月17日月曜日

vimのハイライトを解除する方法

vimで検索してマッチした値がハイライトされるが、
検索が終わった後に出っぱなしになっているとちょっとウザいので、それを消す方法。
結構よく使うくせによく忘れるのでメモ。

:noh

my.cnfの説明及び設定例

■port
通常3306。セキュリティ面から変更したほうがいい。

■key_buffer
インデックスをバッファに保存する際のメモリサイズ。
MyISAMならOSキャッシュも使うので全メモリの30-40%いれるといいらしい。
増やすと検索速度 up
例)key_buffer=256M

■innodb_buffer_pool_size
InnnoDBのバッファのプールサイズ。
InnnoDBはOSキャッシュ使わないので総メモリの70-80%でがんがんいっとけ。

■table_cache
データのキャッシュサイズ。I/O減らすのに有効
数百のテーブルなら1024がベスト。
例)table_cache=256

■thread_cache
スレッドの作成・削除は負荷重いので少なくとも16はほしい。
あとはThreads_Createdの動きを見ながら。

■innodb_additional_pool_size
あんまり効果はないけど20Mほど。

■innodb_log_file_size
ログファイルのサイズ。増やすとパフォーマンスいいけど復旧に時間かかる。
64-512Mくらいまで。

■innodb_log_buffer_size
ログのバッファサイズ。
デフォルトで十分だけど増やしても8MB-16MBくらいまで。

■innodb_flush_log_at_trx_commit
設定しないと激遅。flush logをディスクにとるかメモリかとらないか。
1がディスク、2がメモリ、0がとらない。もちろん2

■max_allowed_packet
入力データ保持のための最大バッファサイズです。でかいファイルに必須。
例)max_allowed_packet=1M

■sort_buffer
ORDER BYやGROUP BYのクエリ速度を上げる。メモリが多くない限り必要なし。
例)sort_buffer=1M

■record_buffer
インデックスを使わないクエリ速度up
例)record_buffer=1M

■long_query_time
この秒数を超えるとslowクエリに認定
例)long_query_time=1

■join_buffer
join用バッファ
例)join_buffer_size = 131072

■query_cache
クエリのキャッシュ量。増やしすぎると更新が反映されない場合もあるので
あまりよくない。データベースのサイズに合わせて
32M-512Mくらいがベスト。

2011年1月16日日曜日

PHP高速化

とりあえずコピーってきたやつ。

01. static にできるメソッドは static として宣言しよう。(4倍速い)
02. echo の方が print より速い。
03. echo '文','字'; (カンマ区切り)の方が、'文'.'字' (ドット連結)より速い。
04. ループの最大値は、ループ「内」ではなく「前」にセットしておこう。
05. 大きい配列のような変数は unset() してメモリを解放しよう。
06. マジックメソッド(例: __get, __set, __autoload)は使用を避けよう。
07. require_once はハイコストなのです。
08. include や require でファイルはフルパスで指定しよう。
09. スクリプト開始時間は time() でなく $_SERVER['REQUEST_TIME'] で取得。
10. 可能であれば、正規表現より strncasecmp、strpbrk、stripos を使おう。


11. strtr(str_replace の4倍速い) > str_replace > preg_replace の順に速い。
12. 引数に配列、文字列両方を受け入れるような関数は避け、個別に関数化しよう。
13. if をたくさん使ってるなら switch を活用しよう。(訳注:ってことでいい?)
14. @によるエラー制御はすんごく遅い。
15. Apache の mod_deflate(Apache2系) を ON にしておこう。(No.42 参照)
16. 処理が終わったらデータベースの接続は切っておこう。
17. $row['id'] は $row[id] より7倍速い。
18. エラーメッセージはハイコスト。
19. for 文の条件式には count($array) のような関数をいれない。(変数に格納)
20. メソッド内ではローカル変数をインクリメントするのが一番速い。


21. グローバル変数のインクリメントはローカル変数より2倍遅い。
22. オブジェクト変数(例:$this->v++)のインクリメントはローカルより3倍遅い。
23. 未定義のローカル変数のインクリメントは定義されたものより9~10倍遅い。
24. 未定義のグローバル変数についても同様。
25. メソッドの起動コストはクラス内のメソッド数とは無関係。
26. 派生クラス内のメソッドは、基底クラスで定義されたメソッドよりも速い。
27. 引数1つの空関数を呼び出すのにも、ローカル変数 $local++ 7~8回分のコスト。
28. ダブルクォート より シングルクォート の方が若干速い。
29. 03 と重複か。(注:これは複数の引数を受け取る echo でのみ有効)
30. PHP スクリプトは静的な HTML ページよりも2~10倍の時間がかかる。


31. キャッシュを利用しよう。通常、コンパイル回数 x 25~100% 分速くなる。
32. これもキャッシュについて。memcached とか使おうよ。
33. if (strlen($foo) < 5) を調べたいなら if (!isset($foo{5})) と書くと速い。
34. $i++ より ++$i の方が速い。(そういう opcode optimizer が走ってる場合)
35. 全部が全部 OOP でなくても良い。(コストやメモリの浪費になってるかも)
36. すべてのデータをクラスにしようとしないこと。配列も十分便利です。
37. メソッドを分割しすぎない。(どれを再利用するのかよく考えよう)
38. メソッドを分割したくなったら後でいくらでもできる。
39. もとから用意されてる 関数たち を活用しよう。
40. 非常に時間のかかる関数 → C言語による拡張モジュール化も検討しよう。


41. コードをプロファイリングしてボトルネックを見つけよう。Xdebug とか。
42. Apache の mod_gzip(Apache 1系)は、転送量を最大80%減。
43. : A HOWTO on Optimizing PHP with tips and methodologies を見てね。
44. 28 と重複か。
45. 13 と重複か。
46. 19 と重複か。
47. ループ処理には foreach を使おう。
48. 複雑なクラスを作ってるなぁと思ったら → Singleton モデルを検討しよう。*2
49. DB に入れる値なら GET より POST を使おう。(パフォーマンスが上がる)
50. 可能なら正規表現より、ctype_alnum、ctype_alpha、ctype_digit を使おう。


51. ファイル指定は basename / file_exists / open_basedir よりフルパス指定が速い。
52. require_once より require を使おう。(opcode キャッシュがらみの理由で)
53. 一時的なファイルを作るときには tmpfile や tempnam を使おう。
54. 外部サービスに XMLHTTP で接続するときにはエラー回避のため Proxy を使おう。
55. デバッグするときは error_reporting (E_ALL); にしておこう。
56. Apache の allowoverride を "none" にしておくとパフォーマンスが向上。
57. 静的なコンテンツには thttpd のような高速なファイルサーバを使おう。
58. パスなどの設定パラメータは配列に serialize して入れ、キャッシュしておこう。
59. アクセスの多いページには PHP の 出力バッファリング を使おう。
60. DB 固有の prepare メソッドではなく PDO::prepare を使おう。


61. SELECT * (ワイルドカード)を使うのはやめよう。
62. PHP より賢い DB ロジック(queries, joins, views, procedures)を活用しよう。
63. SQL の省略表記を活用しよう。
(例:INSERT INTO MYTABLE (FIELD1,FIELD2) VALUES (("x","y"),("p","q"));)

2011年1月14日金曜日

MySQLのエンジンを確認する方法

MyISAMかInnoDBか確認する方法は以下の通り。
show table status;

2011年1月13日木曜日

Linuxのよく使うと思われるシステム関連のコマンド

よく使いそうなコマンドをまとめておく。

システム管理系コマンド


date日付や時刻を表示,設定する
fingerユーザー情報・最新カーネルのバージョンを表示する
freeメモリーの使用状況を表示する
groupaddグループを作成する
groupdelグループを削除する
groupmodグループ情報を変更する
idユーザーIDやグループIDを表示する
last最近ログインしたユーザーの情報を表示する
lastlogユーザーが最後にログインした日付を表示する
passwdユーザーのパスワードを変更する
sg別のグループIDでコマンドを実行する
suユーザーを切り替える
sudo指定したユーザーでコマンドを実行する
unameシステム情報の表示
useraddユーザーを追加する
userdelユーザーを削除する
usermodユーザーのアカウント情報を変更する
vmstatメモリーやCPUの負荷率や使用状況を表示する
wログインしているユーザー名と処理内容を表示する
who現在ログインしているユーザーを表示する

ジョブ・プロセス管理系コマンド

at指定時刻にジョブを実行する
atq実行待ちジョブを表示する
atrm実行待ちジョブを削除する
batch自動的にジョブを実行する
crontabプログラムを定期的に実行するcrondの設定ファイルを編集する
killプロセスおよびジョブを強制終了する
nice優先順位を決めてコマンドを実行する
nohupログアウトした後もコマンドを実行し続ける
pidofプロセスのpidを調べる
ps実行中のプロセスを表示する
pstreeプロセスの親子関係をツリー表示する
sleep指定された時間,停止する
stopバックグラウンドのジョブを停止する
time指定したコマンドの実行時間を表示する
top現在のシステム状況を表示する

モリヤマスポーツの並行輸入品は安いらしい

関西ボーダーの人に聞いたのでメモ。
http://www.morispo.co.jp/

並行輸入品を結構たくさん取り扱っている店らしい。
正規品の40%OFF位の値段で買えるので、安く済ませるならここかも。

2011年1月12日水曜日

変更した.vimrcをすぐに反映させる方法

よく忘れるのでメモ。

:source ~/.vimrc

controllerからviewへの変数の引き渡し方法

オレオレフレームワークで、MVCモデルで実装しようとした場合に、symfonyのようにcontroller(action)からviewに変数を渡すには、controllerの処理の最後にviewのファイルをrequire_onceしてやればよい。

複数ファイル名を一括で変更する

renameコマンドを使うと一括でファイル名を変更することができる。
意外と便利。

2011年1月11日火曜日

grepコマンドで特定のディレクトリを除外して検索する方法

svn管理しているディレクトリ内をgrepする場合は以下のようにするとsvn管理下のファイルがヒットしないようになる。
grep -r --exclude=*.svn* 検索テキスト 対象ディレクトリ

ちなみに「--exclude=*.svn*」の「*.svn*」は正規表現のパターンなので、結構フレキシブルに使える。
grep -r --exclude=正規表現のパターン 検索テキスト 対象ディレクトリ

起動が遅くなってしまったFirefoxの起動を素早く行うspeedfoxが使える

Webページの開発には欠かせないFirefoxですが、長年使っていると起動がどんどん遅くなりストレスに感じることがあります。
そこで使ってほしいのがこの「speedfox」
Firefoxというのは、初回起動時にプロファイルを作成し、そこに設定や履歴、ID、パスワード、ブックマークといった情報を保存しています。
しかし、これが何度も更新されることにより、HDDの断片化と同様の現象が起こります。
そこで使用するのが「speedfox」です。

「speedfox」はwindowsのデフラグツールのようにプロファイルの状態を最適化してくれるツールです。
利用方法も簡単。
まず「speedfox」をダウンロードし、解凍して出てきたexeファイルを実行します。
すると、どのプロファイルに対して実行するのかと、「Run Firefox after optimization」(Firefoxを終了してから最適化を行う)かというチェックボックスがありますので、それぞれ選択し、「Speed Up My Firefox」ボタンを押せば完了します。

僕が使用しているFirefoxも起動までに20秒位かかっていたFirefoxの起動が2秒位で起動するようになりました。
Firefox使いには必須ツールだと思います。

2011年1月6日木曜日

人の振り見て我が振り直せ

新しい会社に入社して一番最初に担当することになった仕事が、外注さんの作った管理ツールの検証と
機能追加だったんですが、ソースを見て愕然としました。

「なんじゃこりゃ・・・。」

なんの気遣いも感じられないソースだった。
インデントがそろってなかったり、無駄にスペース入れてあったり、逆にまったく入ってなかったり。
開発がひと段落しても、必要ないコメント(テスト用のコードとかデバッグコードとか)部分とか消してないし、使ってなさそうなファイルとかもそのまま放置。
こんなので金取るのか?って言うくらいひどいソースでした。

で、なぜ今回タイトルのような記事を書こうと思ったかというと、
自分が書いたソースで、そんな印象を受けさせたくない。
せめて、可読性だけでもきちんと保てるようにプログラムを書いていこうと思ったからだ。

絶対にやらないと決めたことを以下に示す。
PHP編
1.PHPのコーディング規約をなるべく守る。
2.変数名は適当に決めない。($keyとか$valueとか$val1、$val2等)

HTMLコーディング編
1.idやname属性等の情報もきちんとHTMLコーディング規約に則った形で決める。
(同一HTMLファイル内に同一のname属性を持たないようにする等の基本中の基本)
2.FirefoxのHTML Validatorでエラーがある状態のHTMLは完成しているとは言えない。
(HTML単体の場合のみ。PHPなどの出力が混ざってきた場合はよしとする)
3.JavascriptをHTMLソース内にベタ書きでは書かない。
(例外としてごくわずかな量のJSであればありとする)
4.CSSをHTMLソース内にベタ書きでは書かない。
(例外としてごくわずかな量のスタイルであればありとする)

2011年1月5日水曜日

MySQLの文字コードに関して

Server characterset
サーバーのデフォルトキャラクタセット。

Db characterset
デフォルトデータベース(use xxxで選択したデータベース)で使用される文字コード。デフォルトデータベースがまだ選択されていない場合は、Server charactersetと同じものが表示される。

Client characterset
クライアントから送られてくるクエリの文字コードを指定。

Conn. characterset
サーバーはクエリを受信した後に変換する文字コードを指定する。サーバーはクライアントから送られたクエリをClient charactersetからConn. charactersetに変換する。(introducerがない文字列に限る)

vimで改行コードが^Mとなって出てしまっている場合の対処方法

:%s/^M//g
※^MはC-v C-mで入力。

svnでapache経由でコミットしようとしらたエラーになった

VMWare上に作ってあるリポジトリにApache経由でアクセスして使えるようにしたくていろいろとやっていた時のログ。

作業前の状態は以下の通り。
1.Apache経由ではリポジトリを見ることは可能
2.WindowsからTortoiseSVNを使ってチェックアウトすることは可能
3.フォルダを追加してコミットしようとしたらエラーになった。

TortoiseSVNが吐いたエラーは以下の通り。
コミットに失敗しました (詳しい理由は以下のとおりです):
サーバが、リクエストへのレスポンスとして予想外の戻り値 (403 Forbidden) を送信してきました (リクエスト: MKACTIVITY, URL: '/!svn/act/532009ea-04a9-8547-9597-23cc8ad9e5fe')

サーバ側のエラーログは以下の通り。
Access denied: 'ユーザー名' MKACTIVITY /:

ググってみたら結果、これの原因はauthzsvn.confのせいだとわかった。
よく見てみたら、ルートディレクトリ以下は誰も書き込みできないようになっていたので、
管理者は書き込みが可能なように修正して保存。

再度コミットしてみたら今度は別のエラーがでた。
Can’t create directory ‘~~~~~~’: Permission denied

サーバー側のエラーログは以下の通り。
Could not create activity /!svn/act/9a75b9be-5637-be47-9bb1-504df8e09f8a.  [500, #0]
could not begin a transaction  [500, #13]
Can't create directory '/path/to/dir/svn/db/transactions/0-1.txn': Permission denied  [500, #13]

で、これもググってみた結果、リポジトリ内のdavとdbフォルダ以下のオーナーをapacheに変更しないといけないということだったので、さっそく変更

# chown apache:apache -R db/ dav/

もう一度コミットしてみたら、今度はうまくいきました。
よかったよかった。

ちなみに、subversionのバージョンが1.5以降になるとdavディレクトリは自分で作らないといけないらしいので要注意。

サニタイズに関して

サニタイズという言葉を使うなという話。

「入力値の精査=サニタイズ」

は間違い。
サニタイズはそれぞれ適した場所で処理を実行する必要がある。
クロスサイトスクリプティング対策であればHTMLの出力直前に「<」等のタグをエスケープする処理が必要がある。 SQLインジェクション対策であればSQLを実行する前に「'」をエスケープする処理が必要になる。 これを入力値で行おうとすると、必要のないエスケープが行われてしまうことになる。 参考記事 続・「サニタイズ言うなキャンペーン」とは
「サニタイズ言うなキャンペーン」とは
サニタイズ言うなキャンペーンがわかりにくい理由