Category: ソフトウェア

distcc と ccache でビルド高速化


みむらです。

複数台のマシンをお持ちの方、絶対いらっしゃいますよね。
ついでに、隅っこで寝てるとかそういうパターン、絶対ありますよね。

ということで、そういうマシンをコンパイルの際に利用して、是非とも効率よくパワーを使いましょう。

ついでに、ccache を有効にして、キャッシュしましょうという、そんなお話。

追記ですが、 Mac OS X にはこれがなにやら、標準で入っているそうです。
Mac マシンを大量にお持ちの方は、是非ともやってみるといいんじゃないでしょうか!


ということで、カーネルを並列ビルドすることを例にして、使い方。 (Linux Mint 12 でテストしてます。)

 

1.distcc と ccache をインストール。

$ sudo aptitude install distcc ccache

 

2./etc/default/distcc を修正する。

$ sudo vim /etc/default/distcc

# 書き換えるのは下記3点

# 動作を許可させる
STARTDISTCC="false" -> STARTDISTCC="true"

# 接続可能ホストを設定する。
ALLOWEDNETS="127.0.0.1" -> ALLOWEDNETS="192.168.1.0/24"

# リスナとなる NIC の IP アドレスを入力
LISTENER="127.0.0.1" -> LISTENER="192.168.1.200"

 

3. distcc を起動する。

$ sudo service distcc start

 

4. (操作マシン側にて) 接続先のホストを、 DISTCC_HOSTS に設定

(例 192.168.1.200 と 192.168.1.201 が処理マシンだった場合 )

$ export DISTCC_HOSTS="localhost 192.168.1.200 192.168.1.201"

 

5.ビルド

# configure を行う場合
$ CC="ccache distcc gcc" CXX="ccache distcc g++" ./configure

# make を行う場合
#
# なおこの場合、物理コア数の2倍を同時実行数に指定すると、
# なんかいい感じらしいです。
#
# http://distcc.googlecode.com/svn/trunk/doc/web/faq.html
#
# 今回の場合は、各ノードに 4スレッドの CPU が乗っていて、
# 自分と、それ以外の2台のマシンがあると仮定。
#

$ make -j 24 CC="ccache distcc gcc" CXX="ccache distcc g++" HOSTCC="ccache distcc gcc" HOSTCXX="ccache distcc g++"

たぶん、HOSTCC と HOSTCXX の指定は、カーネルビルドの時ぐらいしかいらない気がしなくも。
ついでに、 configure で CC と CXX 指定したら、 make 時はいらなそうな。

とりあえず、自分の備忘録ってことで。メモメモ。

 

追記事項としては、

ビルド環境のコンパイラとかインクルードファイルとかは一緒にしておいた方がいいよということ。
あわせておかないと、面倒なことになるようです。

ソフト面だけ合っていれば問題なさそうなので、ハードウェア面は、プロセッサのアーキテクチャが違うとか、
そういう系を除けば大丈夫だと思います。

SELinux で restorecon してあうあう。


もう、毎回のごとく忘れるので、備忘録。

動かない –> /var/log/audit/audit.log* を見に行く。
毎度のごとく「コンテキストがちげーぜお兄さん」と書かれてる。

そのときに、 chcon で片付けてしまうのが私のひどく悪い癖w

いやね、なんかの拍子に restorecon して、
ぶっ飛ばしてしまうわけですよ。

ということで、それも含めて幅広く、いろいろ備忘録。

 

*ファイル関連。

chcon (CHange file selinux security CONtext)

ファイルとかディレクトリのコンテキストを変える。
一時的にそのファイルに対して、特定のコンテキストを割り当てる時に使うと良さそう

# chcon –t httpd_sys_content_t /home/hogehoge/public_html/ –R

 

ls –aZ

ファイル・ディレクトリに設定されているコンテキストを表示する。
・・要は Z オプションをつける。

# ls –Z
drwxr-xr-x. hogehoge hogehoge unconfined_u:object_r:httpd_user_content_t:s0 public_html

 

restorecon (RESTORE file(s) default selinux security CONtext)

ファイルとかディレクトリのコンテキストをデフォルト設定に戻す。
後述する semanage で恒久的に変更した場合は、その設定に戻る。

(chcon の変更は、restorecon で復元される際に破棄される。)

# restorecon /home/hogehoge/public_html/ –R

 

semanage (SElinux  policy MANAGEment tool)

ファイルとかディレクトリのコンテキストをはじめとする、様々な設定を恒久的に変更する。
このコマンドで変更した内容は、今後もデフォルト設定として保持される。

(ポートに関しては後述)

設定取得 ( –l を使う ) :
# semanage fcontext –l

追加 ( –a を使う ):
# semanage fcontext –a –t httpd_sys_content_t “/home/hogehoge/public_html/(/.*)?”

削除 ( –d を使う ):
# semanage fcontext –d –t httpd_sys_content_t “/home/hogehoge/public_html/(/.*)?”

反映させる ( restorecon を使う ):
# restorecon /home/hogehoge/public_html/ –RF

 

*実行権限関連。

setenforce ( modify the mode selinux is running in. )

Enforcing (制約が施行されてる状態) と Permissive (制約が施行されていない[許可されている] 状態)
の2つを一時的に切り替える。

恒久的に変更する場合は、 /etc/selinux/config の SELINUX を書き換える。

有効にする:
# setenforce 1

無効にする:
# setenforce 0

 

getenforce ( GET the current mode of selinux )

現在、制約が施行されている (Enforcing) か許可されている (Permissive) か、
そもそも動いてないか (Disable) を返す。

# getenforce
Enforcing

 

setsebool (SET SElinux BOOLean value)

ポリシーを変更して、特定の動作を許可したり不許可にしたりという設定ができる。

# setsebool –P ftp_home_dir on

 

getsebool (GET SElinux BOOLean value)

ポリシーを取得したり、全列挙したりする。

全列挙:
# getsebool –a

特定の要素を取得:
# getsebool ftp_home_dir

 

ps –Z

プロセスのドメインを取得する。
・・・要は –Z をつける。

# ps –Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 15287 pts/0 00:00:00 bash

 

*通信ポート関連

semanage (SElinux policy MANAGEment tool)

ファイル操作は先述。プロセスが使用するポートなんかもここで設定。

ポートの設定を取得:
# semanage port –l

ポートの設定を追加 ( FTP を 11111 ポートで動作可能にする )
# semanage port –a –t ftp_port_t –p tcp 11111

ポートの設定削除
# semanage port –d –t ftp_port_t –p tcp 11111

 

とりあえず、こんな感じで。であであ。

小学生にも情報教育をば。


どうもみむらです。

いきなり質問ですが、下記の2つの文章の共通点をあげてください。

A.里の秋。

静かな静かな 里の秋
お背戸に木の実の 落ちる夜は
ああ 母さんとただ二人
栗の実 煮てます いろりばた

B.静かな湖畔

静かな湖畔の 森のかげから
もう起きちゃいかがと カッコが鳴く
カッコ カッコ
カッコ カッコ カッコ

 

はい、もうわかりましたよね。

こたえは、誰しもがわかるあれです。

Continue reading »

Console Twitter を公開しました。


image

ておくれてない、まだ、まだだっ!!
ということでみむらです。

先日の OAuth の記事 を書いた後、やっぱりクライアントを作りましょうということで。

ttytter っぽいものを意識しましたが、自分が使いやすいように作ってみました。

 

Microsoft .NET Framework 3.5 がある環境であれば実行可能です。
(Windows 7 では標準搭載)

 

http://mimumimu.net/software/#ConsoleTwitter
上記URL よりダウンロード可能です。

 

ただつぶやくだけではなく、下記のコマンドを使うことで様々な操作も可能です。

/repリプライ一覧を表示
/rep (番号) (ツイート)リプライを送ります。

ex) /rep 01 ておくれてない!
/favお気に入りに登録したツイートを表示します。
/fav (番号)お気に入りに登録します。
/unfav (番号)お気に入りを解除します。
/rt (番号)リツイートします。
/find (テキスト)指定したテキストで Twitter 上のツイートを検索して表示します。

 

コンソールで表示されて、全部がキーで行うということで、
シンプルでかつ、操作も覚えやすいのでは無いでしょうか。

 

ということで、よろしくお願いします-。


追記:ソースコード公開しました。

https://github.com/mimura1133/Console-Twitter

Twitter の OAuth 1.0 認証を自分でコード書いてやってみた。


みむらです。

ひとまず、おべんきょーということで、後からも分かるように、
変数を多く使って文字列出力をふんだんに出しながら。

ソースコードが、海から来た侵略者に侵略されていますが、
そんなもの全く気にしない、むしろ、侵略されていないでゲソ!

—-

参考資料:

* http://oauth.net/core/1.0
* http://hueniverse.com/oauth/guide/authentication/
* https://dev.twitter.com/docs/auth/authorizing-request/

—-

https://gist.github.com/1395485

using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;

/*
 * この辺を参考に:
 * 
 * http://oauth.net/core/1.0
 * http://hueniverse.com/oauth/guide/authentication/
 * https://dev.twitter.com/docs/auth/authorizing-request
 */

namespace Direct_Commit_Twitter
{
    class Program
    {

        static void Main(string[] args)
        {
            //
            // 使うパラメータは次のようなもの。
            //
            // OAuth Consumer Key       : Consumer Key そのまま。
            // OAuth Token              : Access Token そのまま。 (今回はこれも取得。)
            // OAuth Nonce              : ランダム文字列を与える。 (毎回変更する。)
            // OAuth Signature          : OAuth Signature 以外の値で HMAC-SHA1 をとった値。
            // OAuth Signature Method   : Twitter は HMAC-SHA1 指定っぽいので HMAC-SHA1.
            // OAuth Time Stamp         : UNIX 時間 (1970-01-01 UTC からの秒数) を与える。
            //                          : (今回は GetUNIXTime() メソッドで取得します。)
            // OAuth Version            : 今回は 1.0 を使うので、1.0.
            //

            string consumer_key = "oDcUp76alv6VctYvRx2g";
            string consumer_secret = "mg1U9TEFVafIPQm0Y0YuLR8EZatXiDBvPLiiCConzbg";

            string access_token = "";
            string access_secret = "";

            string tweet_text = "ゲソーゲソー";

            /************************ 以下、黙々と処理 ********************/

            string[] verify_token;

            if (access_token == "" || access_secret == "")
            {

                #region 01. Request Token を取得しなイカ?
                {
                    Console.WriteLine("01 - Token を取得しなイカ?");
                    Console.WriteLine("-------------------------------------------------");

                    Random rand = new Random();
                    byte[] nonce_b = new byte[64];

                    rand.NextBytes(nonce_b);

                    string nonce = Math.Abs(BitConverter.ToInt64(nonce_b, 0)).ToString();
                    long unixtime = GetUNIXTime();

                    //
                    // OAuth Signature 生成のために、それ以外で仮のリクエスト文字列を作成する。
                    // この際、各パラメータは ABC 順にソートされている必要がある。
                    //
                    string signature_request = "POST&" + UrlEncode("https://api.twitter.com/oauth/request_token");
                    signature_request += "&" + UrlEncode(MakeParamString(consumer_key, nonce, null, unixtime, null, null, null));

                    //
                    // ちゃんとしたリクエスト文字列を作る。
                    //
                    string signature = GetSignature(consumer_secret, null, signature_request);
                    string param = MakeParamString(consumer_key, nonce, signature, unixtime, null, null, null);

                    DebugParamOut(consumer_key, consumer_secret, nonce, signature, unixtime, null, null, null);
                    return;
                    //
                    // 問い合わせ。
                    //
                    Console.WriteLine("* Access : https://api.twitter.com/oauth/request_token?" + param);
                    HttpWebRequest hwr = (HttpWebRequest)HttpWebRequest.Create("https://api.twitter.com/oauth/request_token?" + param);
                    hwr.Method = "POST";
                    WebResponse ret = hwr.GetResponse();
                    verify_token = new StreamReader(ret.GetResponseStream()).ReadToEnd().Split('&');

                    ret.Close();

                    Console.WriteLine();
                    Console.WriteLine("Response : ");
                    foreach (string s in verify_token)
                        Console.WriteLine("> " + s);
                }
                #endregion

                #region 02. Access Token を取得しなイカ?
                {
                    Console.WriteLine();
                    Console.WriteLine("02 - Access Token を取得しなイカ?");
                    Console.WriteLine("-------------------------------------------------");

                    string request_token = "";
                    string request_secret = "";

                    //
                    // ブラウザ開いて認証。
                    //
                    foreach (string s in verify_token)
                    {
                        int p = s.IndexOf("oauth_token=");
                        if (p != -1)
                        {
                            request_token = s.Substring(p + "oauth_token=".Length);
                            break;
                        }
                    }
                    Console.WriteLine("- OAuth Token : " + request_token);
                    Console.WriteLine("* Browser Open : https://twitter.com/oauth/authorize?oauth_token=" + request_token);
                    Process.Start("https://twitter.com/oauth/authorize?oauth_token=" + request_token);

                    //
                    // PIN を入力させる。
                    //
                    Console.Write("\nINPUT PIN : ");
                    string pin = Console.ReadLine();

                    foreach (string s in verify_token)
                    {
                        int p = s.IndexOf("oauth_token_secret=");
                        if (p != -1)
                        {
                            request_secret = s.Substring(p + "oauth_token_secret=".Length);
                            break;
                        }
                    }


                    //
                    // 以下 Twitter ともくもく通信。
                    //

                    Random rand = new Random();
                    byte[] nonce_b = new byte[64];

                    rand.NextBytes(nonce_b);

                    string nonce = Math.Abs(BitConverter.ToInt64(nonce_b, 0)).ToString();
                    long unixtime = GetUNIXTime();

                    //
                    // Signature 生成のための一時的なリクエスト文字列を作成。
                    //
                    string signature_request = "POST&" + UrlEncode("https://api.twitter.com/oauth/access_token");
                    signature_request += "&" + UrlEncode(MakeParamString(consumer_key, nonce, null, unixtime, request_token, pin, null));

                    string signature = GetSignature(consumer_secret, request_secret, signature_request);
                    string param = MakeParamString(consumer_key, nonce, signature, unixtime, request_token, pin, null);

                    DebugParamOut(consumer_key, consumer_secret, nonce, signature, unixtime, request_token, request_secret, pin);

                    //
                    // 問い合わせ。
                    //
                    Console.WriteLine("* Access : https://api.twitter.com/oauth/access_token?" + param);
                    HttpWebRequest hwr = (HttpWebRequest)HttpWebRequest.Create("https://api.twitter.com/oauth/access_token?" + param);
                    hwr.Method = "POST";
                    hwr.Headers.Add("Authorization", "OAuth");

                    WebResponse ret = hwr.GetResponse();
                    verify_token = new StreamReader(ret.GetResponseStream()).ReadToEnd().Split('&');

                    ret.Close();

                    Console.WriteLine();
                    Console.WriteLine("Response : ");
                    foreach (string s in verify_token)
                    {
                        if (s.IndexOf("oauth_token=") != -1)
                            access_token = s.Substring(s.IndexOf("=") + 1);

                        if (s.IndexOf("oauth_token_secret=") != -1)
                            access_secret = s.Substring(s.IndexOf("=") + 1);

                        Console.WriteLine("> " + s);
                    }
                }
                #endregion

            }

            #region 03. つぶやかなイカ?
            {
                Console.WriteLine();
                Console.WriteLine("03 - つぶやかなイカ?");
                Console.WriteLine("-------------------------------------------------");
                
                Random rand = new Random();
                byte[] nonce_b = new byte[64];

                rand.NextBytes(nonce_b);

                string nonce = Math.Abs(BitConverter.ToInt64(nonce_b, 0)).ToString();
                long unixtime = GetUNIXTime();

                string tweet_data = UrlEncode(tweet_text);

                string signature_request = "POST&" + UrlEncode("https://api.twitter.com/1/statuses/update.xml");
                signature_request += "&include_entities%3Dtrue%26" + UrlEncode(MakeParamString(consumer_key, nonce, null, unixtime, access_token, null, tweet_data));
                string signature = GetSignature(consumer_secret, access_secret, signature_request);

                string header_param = "OAuth oauth_consumer_key=\"" + UrlEncode(consumer_key) + "\",oauth_signature_method=\"HMAC-SHA1\"," +
                                      "oauth_timestamp=\"" + unixtime + "\",oauth_nonce=\"" + UrlEncode(nonce) + "\"," +
                                      "oauth_version=\"1.0\",oauth_token=\"" + UrlEncode(access_token) + "\"," +
                                      "oauth_signature=\"" + UrlEncode(signature) + "\",";

                DebugParamOut(consumer_key, consumer_secret, nonce, signature, unixtime, access_token, access_secret, null);
                Console.WriteLine("* Access : https://api.twitter.com/1/statuses/update.xml");
                Console.WriteLine("* Tweet at : " + tweet_text);

                HttpWebRequest hwr = (HttpWebRequest)HttpWebRequest.Create("https://api.twitter.com/1/statuses/update.xml");
                hwr.Method = "POST";
                hwr.ServicePoint.Expect100Continue = false;
                hwr.Headers.Add(HttpRequestHeader.Authorization, header_param);
                hwr.ContentType = "application/x-www-form-urlencoded";
                var s = new StreamWriter(hwr.GetRequestStream());
                s.Write("status=" + tweet_data + "&include_entities=true");
                s.Close();

                WebResponse ret = hwr.GetResponse();
                Console.WriteLine();
                Console.WriteLine("Response:");
                Console.WriteLine("> "+(new StreamReader(ret.GetResponseStream()).ReadToEnd()));

            }
            #endregion
        }

        // UNIX 時間を返す。
        static long GetUNIXTime()
        {
            return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
        }

        // URLエンコード (どうやらエスケープ文字は大文字にしないといけないらしい。)
        static string UrlEncode(string str)
        {
            string s = HttpUtility.UrlEncode(str);
            return _UrlEncodeUpper(s);
        }

        static string _UrlEncodeUpper(string str)
        {
            int p = str.IndexOf("%");
            if (p != -1)
            {
                str = str.Substring(0, p) + str.Substring(p, 3).ToUpper() + _UrlEncodeUpper(str.Substring(p + 3));
            }
            return str;
        }

        // パラメータ文字列を生成
        static string MakeParamString(string oauth_consumer_key, string oauth_nonce, string oauth_signature, long oauth_timestamp, string oauth_token, string oauth_verifier, string status)
        {
            string param = "oauth_consumer_key=" + oauth_consumer_key + "&oauth_nonce=" + oauth_nonce;

            if (oauth_signature != null)
                param += "&oauth_signature=" + oauth_signature;

            param += "&oauth_signature_method=HMAC-SHA1" + "&oauth_timestamp=" + oauth_timestamp;

            if (oauth_token != null)
                param += "&oauth_token=" + oauth_token;

            if (oauth_verifier != null)
                param += "&oauth_verifier=" + oauth_verifier;
            
            param += "&oauth_version=1.0";

            if (status != null)
                param += "&status=" + status;

            return param;
        }

        // Consumer Secret をKey とした、リクエスト文字列のハッシュを求める。
        static string GetSignature(string consumer_secret, string access_token_secret, string param)
        {
            HMACSHA1 hmacsha1 = new HMACSHA1();
            hmacsha1.Key = Encoding.ASCII.GetBytes(consumer_secret + "&" + access_token_secret);
            byte[] hash = hmacsha1.ComputeHash(Encoding.ASCII.GetBytes(param));
            
            return Convert.ToBase64String(hash);
        }

        // よくやる出力をまとめてみる。
        static void DebugParamOut(string oauth_consumer_key, string oauth_consumer_secret, string oauth_nonce, string oauth_signature, long oauth_timestamp, string oauth_token, string oauth_token_secret, string oauth_verifier)
        {
            Console.WriteLine("- OAuth Consumer Key = " + oauth_consumer_key);
            Console.WriteLine("- OAuth Consumer Secret = " + oauth_consumer_secret);
            Console.WriteLine("- OAuth Nonce = " + oauth_nonce);
            if (oauth_signature != null)
                Console.WriteLine("- OAuth Signature = " + oauth_signature);
            Console.WriteLine("- OAuth Time Stamp = " + oauth_timestamp);
            if (oauth_token != null)
                Console.WriteLine("- OAuth Access Token = " + oauth_token);
            if (oauth_token_secret != null)
                Console.WriteLine("- OAuth Access Token Secret = " + oauth_token_secret);
            if (oauth_verifier != null)
                Console.WriteLine("- OAuth Verifier = " + oauth_verifier);
        }
    }
}

 

とりあえず、記事自体がむちゃくちゃ長くなるので、
解説云々は次の記事に。