2013年8月31日土曜日

Ubuntu13.04 で usermod -G やらかした後の復旧まとめ

Ubuntuでやりがち(だよね?)なミス、usermod -Gでユーザグループ追加しようとして、管理グループからユーザを外してしまいsudo出来なくなるアレ。
最近、自宅の仮想環境上のUbuntuに触ってなかったんですが、久々にログインしたらsudo権限が無く……。
前に吹っ飛ばしたままだったようなので、復旧させました。

せっかくなんで手順メモ。
SSはとり忘れたッス。


  1. 再起動してリカバリーモードで起動しなおす。
    Shift押しっぱなしにすると、GRUBが開くので、
    Advanced options for Ubuntuを選択。
    一覧から(recovery mode)とついたOSを選択。たくさん出たら上にあるやつでいいです。
  2. fsckを選択して、Read/Writeモードでマウントしなおす。
    リカバリーモード起動時は、ファイルシステムがリードオンリーなので、
    このままだと/etc/groupに書き込みすることが出来ず、グループの追加が行えません。
    なので、書き込み可能状態で再マウントする必要があります。
    本来、fsckコマンドは、ファイルシステムをチェックするコマンドですが、
    リカバリーモードの場合、実行後にファイルシステムを再マウントしてくれます。
  3. rootを選択して、ターミナルを起動。
  4. gpasswdコマンドでsudoグループにユーザを追加。
    gpasswd -a user_name sudo
    コマンドは上記のものを使いましょう。
    usermod -GはUbuntuで利用すると、指定したグループ以外を消してしまうようなので。
    普段使うときもgpasswdのほうがいいです。Ubuntuだったら。(Debianはどうなんだろう…)
  5. resumeで再起動。
  6. sudoして確認してみる。
こんな感じ。
ポイントをまとめると、
  • リカバリーモード起動直後は、リードオンリーで書き込みが出来ない。
    書き込み可能で再マウントするにはfsckを実行する。
  • Ubuntu 13.04の場合、sudo可能なグループはsudo
    昔はadminだった気がする…。いつ変わったんだろう?
こんな感じですかねー。

Ubuntu、日本だけかもしれないけど、9~11位のバージョンのときが流行のピークで
Google先生に聞いてもそれくらいのバージョンのときの解決方法が上のほうに出てくるんですよね。
すると、今の最新とは結構違った内容が出てきちゃったりします。

まぁ、GnomeからUnityになったあたりと、Macが開発用端末として流行り始めた時期から、
ユーザが減ったんだろうけど…。

出始めは悪評多かったUnityですけど、最新だと結構きれいに動くし、
VirtualBox上でも設定さえしっかりすればきれいに動いてくれるので
個人的には、これからも最新バージョンを追って使い続けたいディストリだったりします。

2013年8月28日水曜日

Symfony2のblog tutorialを2.3に対応させる。

Symfony2、これまでほぼノータッチだったんですが、触る必要が出てきたので、
ざっと基本的な部分を把握するために、blogチュートリアルをやってみました。

URLはこちら。
※海外有志の方が作成した、symblogチュートリアルじゃない方です。

こちら、ヘッダ部分に記載されているとおり、バージョン2.0.7向けの内容です。
ですが、現在最新のSymfony2は2.3.4。
deprecatedになっているメソッドがあったり、そもそも存在しないAPIがあったりするので、
いくつか、気づいた変更点をまとめておきます。

  1. getEntityManegerメソッドがdeprecated。
    DB操作を行う、EntityManagerを取得するメソッド名が変更になっています。
    使い方はそのままなので、単純にメソッド名を変えれば良さそう。
    http://docs.symfony.gr.jp/sf2-blog-tutorial/05-list-page.html
    例えば、上のページのDefaultController.phpのindexActionは以下のようになります。
    public function indexAction()
    {
    //    $em = $this->getDoctrine()->getEntityManager();  // 旧
        $em = $this->getDoctrine()->getManager();  // 新
        $posts = $em->getRepository('MyBlogBundle:Post')->findAll();
  2. FormのbindRequestメソッドが廃止。
    リクエストをバインドする時は、単純にbindメソッドを使えば良いよう。
    http://docs.symfony.gr.jp/sf2-blog-tutorial/07-create-form.html
    例えば、上のページのDefaultController.phpのnewActionのバリデーション周りは以下のようになります。
    // バリデーション
    $request = $this->getRequest();
    if ('POST' === $request->getMethod()) {
    //    $form->bindRequest($request);  // 修正前
        $form->bind($request);    // 修正後
        if ($form->isValid()) {
    
  3. フラッシュメッセージ関連
    Session周りのAPIが変更になった影響で、フラッシュメッセージの設定方法、表示方法共に変更となっています。
    まず、大きな変更として、フラッシュメッセージは常に配列で扱われるようになった、という所があるようです。
    ですので、表示の際は配列であることを意識したビューの書き方をする必要があります。

    フラッシュメッセージを設定するController側の変更です。
    http://docs.symfony.gr.jp/sf2-blog-tutorial/customize/03-session-flash.html
    上のページのDefaultController.phpのnewActionは以下のようになります。
    public function newAction()
        {
            // ...
    //        $this->get('session')->setFlash('my_blog', '記事を追加しました');  // 修正前
            $this->get('session')->getFlashBag()->add('my_blog', '記事を追加しました');    // 修正後
            return $this->redirect($this->generateUrl('blog_index'));
            // ...
        }
    ちなみに、FlashBagにmessageを設定するメソッドは、add以外にsetもあります。
    違いは何かというと、FlashBag.phpのソースを直接見るとわかりやすいのですが、
    add: $this->flashes[$type][] = $message;
    set: $this->flashes[$type] = $messages;
    と、addは指定したtypeの配列にメッセージ(文字列)を追加するのに対し、
    setは指定したtypeの配列そのものを上書きする形になります。
    なので、普通に使う分にはadd使ったほうが良いんじゃないかと思います。

    次、テンプレート側の変更。
    http://docs.symfony.gr.jp/sf2-blog-tutorial/customize/03-session-flash.html
    同じく上のページのindex.html.twigのフラッシュメッセージ周りは以下のようになります。
    {% for type, messages in app.session.flashbag.all() %}
        {% for message in messages %}
            
    {{ message }}
    {% endfor %} {% endfor %}
    ちょっとこれは、変更前/後の比較表示が難しいので、変更後だけ。
    一見するとコードが増えて複雑なように見えますが、システムが複雑化してきて、
    フラッシュメッセージの量や種類が増えてくると、便利なんじゃないかな、と。
    (とはいえ、一度に大量のフラッシュメッセージが表示されるサービスは、微妙なようにも思いますが…ww)
  4. FormTypeのgetDefaultOptionsメソッドが廃止。
    変わりに追加となった、setDefaultOptionsを利用することになります。
    http://docs.symfony.gr.jp/sf2-blog-tutorial/customize/05-create-form-class.html
    上のページの"PostType.php"のgetDefaultOptionsは以下のようになります。
    // use周りも追加・変更があるので注意
    use Symfony\Component\Form\AbstractType;
    // use Symfony\Component\Form\FormBuilder; // 削除
    use Symfony\Component\Form\FormBuilderInterface; // 追加
    use Symfony\Component\OptionsResolver\OptionsResolverInterface; // 追加
    
    // 中略
    
        public function setDefaultOptions(OptionsResolverInterface $resolver) {
            $resolver->setDefaults(array(
                'data_class' => 'My\BlogBUndle\Entity\Post',
            ));
        }
    戻り値として返すのではなく、$resolverのsetDefaultsに設定する形になった、と覚えればOKでしょう。たぶん。
    ちなみに、同時に廃止となったgetAllowedValuesメソッドの役割も$resolverに対して行うようです。
気づいたのは大体こんな感じですね。
deprecatedなメソッドは、もしかしたら見落としがまだあるかもしれません。
詳しくは、SymfonyのUPGRADE-2.x.mdを見るのがいいと思います。
2.1, 2.2までは有志の方が日本語に訳してくださったものがあるのでそれを参考にするとわかりやすいと思います。
上で書かれている内容は、2.1のタイミングで変更になったものばかりでした。