Hatena::ブログ(Diary)

vivid memo このページをアンテナに追加 RSSフィード

vivid code というサイトのメモ代わりにブログを書いています

2011-11-03

Ubuntu 11.10 で全てのユーザーを一般ユーザー (admin グループに属してない) にしてしまった場合の対処法

Ubuntu では、特権を得るために原則として root ユーザーになることはせず、管理者ユーザー (admin グループに所属しているユーザー) が sudo コマンド (グラフィカルプログラムの場合は gksudo など) を使うことで特権を得ます (Ubuntu document - RootSudo)。 そのため、ユーザーが所属するグループを変更するときには注意しなければいけません。 間違って全てのユーザーを admin グループから取り除いてしまう (全てのユーザーが管理者ユーザーではなくなってしまう) と少し復旧に手間がかかってしまいます。

ここでは、間違って全てのユーザーを admin グループから除いてしまった場合の復旧方法について述べます。

Ubuntu でユーザーをグループに追加するときにしてはいけないこと

間違って全てのユーザーを admin グループから除く、なんてことは GUI のみの操作をしていれば (多分) できないと思うのですが、コマンド操作をしているとついやってしまう失敗ではないでしょうか。

上記の記事に書いているように、usermod コマンドを使用してユーザーの所属グループを変更するときに、元々所属しているグループを記述し忘れてしまうという失敗はやりがちです。 この失敗を元々 admin グループに属しているユーザーに対してしてしまうと (そしてそのユーザーが唯一の管理者ユーザーだと) 管理者ユーザーが居ないという状況になってしまいます。 理由はわかりませんが、ログアウトするまでは sudo 権限は残っているようなので (グループ情報が読み込まれるのがログイン時だから? sudo 権限が付与されるのがログイン時だから?) admin グループから除いてしまってもログアウトするまでに気づけば直せるのですが、一度ログアウトしてしまうと誰も sudo 権限を持っておらず復旧が困難になります。

sudo 権限がないと、グループを変更しようとしても以下のようになって変更できないのです。

~$ sudo usermod -g usergroup -G usergroup,admin username
username is not in the sudoers file

Ubuntu 11.10 だと recovery menu のシングルユーザーモードから復旧できない?

上に挙げた 2 つの記事では、復旧方法として recovery menu のシングルユーザーモードでログインして usermod コマンドを使うという方法を書いています。 (/etc/group ファイルを変更してもよいでしょう。)

また、Ubuntu 11.10 のドキュメントの 「I forgot my password!」 にはパスワードを忘れた際の対処法として、同様のシングルユーザーモードでのログインによる復旧方法が書かれています。

しかしながら、私の環境で試してみたところ recovery menu のシングルユーザーモードでログインしても、usermod コマンドがうまくいきませんでした。 (以下のように /etc/passwd がロックできなかったと言われた。)

~# usermod -g usergroup -G usergroup,admin username
usermod: cannot lock /etc/passwd; try again later

また /etc/group ファイルの編集もできませんでした (Read-only だと言われる)。 chmod コマンドを使っても以下のようにエラーが発生。

~# chmod 0666 /etc/group
chmod: changing permissions of `/etc/group' : Read-only file system

パスワードの変更も同様で、以下のようなエラーが発生してできませんでした。 Ubuntu 11.10 のヘルプドキュメントに書かれている方法なので私が何か間違っているのかもしれませんが。。

~# passwd username
passwd: Authentication token manipulation error
passwd: password unchanged

(追記) コメントで教えていただいたのですが、recovery mode で起動する方法で復旧できるようです。 私はまだ試していませんが、必要でしたらこの記事のコメントを参照して試してください。

解決策

そんなわけで recovery mode を使う方法では上手くいかなかったので、復旧方法として別の方法をとりました。 大まかな方法としては、Live Disk で Linux をオンメモリで動かし、HDD に書かれているファイルの内容を変更する、というものです。 以下に簡単に手順を書いておきます。

  1. Live Disk で Ubuntu 11.10 起動
  2. 以下のようなコマンドで HDD のファイルシステムをマウントする (/dev/sda1 は環境依存なので適当に変更のこと)
    ~$ sudo mkdir /mnt/myhdd
    ~$ sudo mount /dev/sda1 /mnt/myhdd
  3. ファイルの中身を確認しマウントしたデバイスが正しい HDD かどうかチェックする
  4. 以下のコマンドでもともとの /etc/group にあたるファイルを開く (vi じゃなくても使いやすいエディタを使ってください)
    ~$ sudo vi /mnt/myhdd/etc/group
  5. 以下のように admin グループについて書かれた行にユーザーを追加
    admin:x:118:username
  6. 変更を保存して再起動して、HDD 上の Ubuntu 11.10 を起動

これでうまくいくはずです。

Ubuntu の admin グループと sudo 権限の関係

今日の朝書いた記事 「Ubuntu 11.10 で全てのユーザーを一般ユーザー (admin グループに属してない) にしてしまった場合の対処法」 で書いたように、Ubuntu では admin グループに属しているユーザーが管理者ユーザーになります。 また、どのユーザーに sudo 権限を与えるかは /etc/sudoers というファイルで指定されます。

では admin グループ (管理者ユーザー) と sudo 権限 (/etc/sudoers の内容) はどういう関係になっているのでしょうか? /etc/sudoers の中を覗いてみると、以下のような 2 行がありました。

# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL

つまり、admin グループのメンバーに sudo 権限を付与するように /etc/sudoers が記述されている、というわけです。

参考

2011-10-25

Facebook のユーザー認証と REST API (Graph API) の基本 (web アプリの場合)

Twitter の REST API を使うのと同じように Facebook の API を使いたいけどドキュメントがよくわからない、と前に思って放置してたんですが、読書メーターの Facebook 連携がうまくいかない原因を調べようと思って Facebook の API を使ってみると意外と簡単だったのでメモしておきます。

Web サービスから Facebook の API を使うことを想定しています。

まずはアプリケーションの登録

Facebook のアプリ管理アプリ https://developers.facebook.com/apps を使って自分のアプリを登録します。 「Create New App」 というボタンをクリックしてアプリの登録を行います。 アプリ登録の際には、開発者の承認のために携帯電話の番号かクレジットカード番号を登録しておく必要があります。

アプリの登録が終わると、アプリ用の App ID と App Secret が発行されます。

ユーザーごとのアクセストークンの取得

Twitter では OAuth 1.0a を用いてユーザー認証を行いますが、Facebook では OAuth 2.0 を用いてユーザー認証を行います。 その流れを簡単に説明します。 詳細は Facebook の開発者向けドキュメントを見てください。

1. ユーザーを Facebook ページに誘導し、自分のアプリを許可して貰う

ユーザーを

https://www.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&redirect_uri=YOUR_URL

というページに誘導します。 これはアプリからユーザーの情報にアクセスすることを許可するかどうかをユーザーに尋ねるページです。 YOUR_APP_ID は自分のアプリの ID です。 YOUR_URL は、ユーザーがアプリを許可した後に遷移するページの URL です。 この URL のドメインは、アプリ登録時に web site の site url として記入しておかなければいけません。 (セキュリティ機能のため; 後から変更も出来る。)

また、ユーザーの情報にアクセスするだけでなく、ユーザーの wall への書き込みの許可などが必要な場合は、scope パラメータを追加してそれを指定します。 詳しくは公式のドキュメントを見てください。

2. ユーザーが許可すればリダイレクト

ユーザーがアプリを許可すると、YOUR_URL?code=A_CODE_GENERATED_BY_SERVER にリダイレクトされます。 このとき渡される A_CODE_GENERATED_BY_SERVER を使用して Facebook 側にアクセストークンの発行をリクエストします。

3. アクセストークンを取得

2. で取得した A_CODE_GENERATED_BY_SERVER を使って、

https://graph.facebook.com/oauth/access_token?client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&client_secret=YOUR_APP_SECRET&code=A_CODE_GENERATED_BY_SERVER

に GET メソッドでリクエストを発行します。 YOUR_APP_IDYOUR_APP_SECRET は、アプリの登録をすることによって発行してもらえる値です。 YOUR_URL はなぜ必要なのかよくわかりませんが、とりあえず 1. で使用した値と同じ値でよいと思います。

エラーが発生しなければ、レスポンスとして以下のような文字列を得られます。

access_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&expires=6694

これでアクセストークンの取得が完了しました。 access_token パラメータの値がアクセストークンです。 これ以降はこのトークンを使うことで、アプリからユーザーの情報にアクセスしたり、(許可をしてもらっているならば) ユーザーの wall に投稿したりできるようになります。 expires は、このアクセストークンがいつまで有効かを表しています。 (特にユーザーに許可を求めなければ、アクセストークンは期限付きになる; 無期限のアクセストークンにするように最初にユーザーに許可を求めることも可能。)

Graph API を使用する

ユーザーの情報などにアクセスするためには Graph API というものを使用します。 詳細は公式のドキュメントを見てください。

この API にリクエストを投げる際に、パラメータとして access_token=XXXXXXX の形式でさきほど取得したアクセストークンを指定すると、そのアクセストークンを使用できます。

ユーザーの情報にアクセスする例

例えば、自分のユーザー ID を取得するための リクエストメソッドと URL は

GET - https://graph.facebook.com/me

ですので、アクセストークンのユーザーの ID を知りたい場合は

https://graph.facebook.com/me?access_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

という URL に GET メソッドでリクエストを投げればよいことになります。

また、wall に投稿するための API として

POST - https://graph.facebook.com/ID/feed

がありますので、ID が ID の人の wall にメッセージを投げる場合は

https://graph.facebook.com/ID/feed

という URL に

access_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&&message=HELLO

というメッセージボディを POST すればよいことになります。

アクセストークンの文字数

結局、読書メーターの Facebook 連携がうまくいかないことがあった原因はアクセストークンの文字数を少なく見積もっていたことだったようです [ http://akahoshitakuya.com/archives/4026 ] が、Facebook のアクセストークンの文字数はユーザーによってまちまちのようですので、アクセストークンの文字数の上限がどうなっているのかの仕様を確認せずにアプリ内でのアクセストークンの文字数を制限することはしないようにしましょう。

2011-10-14

HTML 要素にクラスを付与したり削除したりするのに便利なユーティリティメソッド (JavaScript)

HTML5 における HTMLElement#classList

HTML5 では、HTML DOM の HTMLElement インターフェイスに classList というプロパティ が追加される予定です。 このプロパティは W3C DOM 4 の DOMTokenList インターフェイス を実装したオブジェクトを参照しており、このリストに値を追加したり、このリストから値を削除すると、要素のクラス属性に反映されます。

つまり、HTMLElement#classList を使うことで、要素にクラスを追加したり削除したりすることが簡単にできます。 詳細は MDN あたりが分かりやすいと思います。

しかしながら、現在のところ HTMLElement#classList が使える環境は多くはありません。 Firefox 7 や Opera 11.51 では使えることを確認しました (Google Chrome でも使えるようです) が、Safari 5 や IE 10 では実装されていません。

続きを読む

2011-10-02

書評: 『ハイパフォーマンス JavaScript』 Nicholas C. Zakas 著, 水野 貴明 訳

ハイパフォーマンスJavaScript

ハイパフォーマンスJavaScript

『ハイパフォーマンス JavaScript』 を読み終わりました。 簡単に内容についてと感想を書いておきます。

続きを読む

2011-08-26

pg_stat_statements を使って遅いクエリを見つける (PostgreSQL, Ubuntu 10.04)

PostgreSQL などのリレーショナルデータベース (RDB) に対して発行されたクエリのうち、どのクエリで時間がかかっているのかを調べることは重要です。 そのための手段は色々ありますが、ここでは PostgreSQL のバージョン 8.4 以降で使用できる pg_stat_statements について、Ubuntu での使い方を説明します。

続きを読む