yumのパッケージ(rpm)をダウンロードする方法

yumdownloaderというコマンドを使えば、インストールは行わずにパッケージのrpmだけを取得できる模様。

# yumdownloaderのインストール
$ sudo yum install yum-utils

# vimのrpmを取得
$ yumdownloader vim
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.jaist.ac.jp
 * extras: ftp.jaist.ac.jp
 * updates: ftp.jaist.ac.jp
vim-enhanced-7.4.160-1.el7.x86_64.rpm     

# gccおよびその依存パッケージのrpmを取得
$ yumdownloader --resolve gcc
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.jaist.ac.jp
 * extras: ftp.jaist.ac.jp
 * updates: ftp.jaist.ac.jp
--> Running transaction check
---> Package gcc.x86_64 0:4.8.3-9.el7 will be installed
--> Processing Dependency: cpp = 4.8.3-9.el7 for package: gcc-4.8.3-9.el7.x86_64
--> Processing Dependency: glibc-devel >= 2.2.90-12 for package: gcc-4.8.3-9.el7.x86_64
--> Processing Dependency: libmpfr.so.4()(64bit) for package: gcc-4.8.3-9.el7.x86_64
--> Processing Dependency: libmpc.so.3()(64bit) for package: gcc-4.8.3-9.el7.x86_64
--> Running transaction check
---> Package cpp.x86_64 0:4.8.3-9.el7 will be installed
---> Package glibc-devel.x86_64 0:2.17-78.el7 will be installed
--> Processing Dependency: glibc-headers = 2.17-78.el7 for package: glibc-devel-2.17-78.el7.x86_64
--> Processing Dependency: glibc-headers for package: glibc-devel-2.17-78.el7.x86_64
---> Package libmpc.x86_64 0:1.0.1-3.el7 will be installed
---> Package mpfr.x86_64 0:3.1.1-4.el7 will be installed
--> Running transaction check
---> Package glibc-headers.x86_64 0:2.17-78.el7 will be installed
--> Processing Dependency: kernel-headers >= 2.2.1 for package: glibc-headers-2.17-78.el7.x86_64
--> Processing Dependency: kernel-headers for package: glibc-headers-2.17-78.el7.x86_64
--> Running transaction check
---> Package kernel-headers.x86_64 0:3.10.0-229.4.2.el7 will be installed
--> Finished Dependency Resolution
(1/7): glibc-headers-2.17-78.el7.x86_64.rpm                                                                                                                                                                                        | 656 kB  00:00:01     
(2/7): libmpc-1.0.1-3.el7.x86_64.rpm                                                                                                                                                                                               |  51 kB  00:00:00     
(3/7): mpfr-3.1.1-4.el7.x86_64.rpm                                                                                                                                                                                                 | 203 kB  00:00:00     
(4/7): kernel-headers-3.10.0-229.4.2.el7.x86_64.rpm                                                                                                                                                                                | 2.3 MB  00:00:02     
(5/7): cpp-4.8.3-9.el7.x86_64.rpm                                                                                                                                                                                                  | 5.9 MB  00:00:04     
(6/7): glibc-devel-2.17-78.el7.x86_64.rpm                                                                                                                                                                                          | 1.0 MB  00:00:05     
(7/7): gcc-4.8.3-9.el7.x86_64.rpm         

$ ls -l *.rpm
-rw-r--r-- 1 root root  6223284 Mar 14 07:43 cpp-4.8.3-9.el7.x86_64.rpm
-rw-r--r-- 1 root root 16887940 Mar 14 07:49 gcc-4.8.3-9.el7.x86_64.rpm
-rw-r--r-- 1 root root  1093332 Mar 14 07:50 glibc-devel-2.17-78.el7.x86_64.rpm
-rw-r--r-- 1 root root   671684 Mar 14 07:50 glibc-headers-2.17-78.el7.x86_64.rpm
-rw-r--r-- 1 root root  2392088 May 13 16:25 kernel-headers-3.10.0-229.4.2.el7.x86_64.rpm
-rw-r--r-- 1 root root    51732 Jul  4  2014 libmpc-1.0.1-3.el7.x86_64.rpm
-rw-r--r-- 1 root root   208316 Jul  4  2014 mpfr-3.1.1-4.el7.x86_64.rpm
-rw-r--r-- 1 root root  1084932 Jul  4  2014 vim-enhanced-7.4.160-1.el7.x86_64.rpm

依存パッケージも含めてまとめてrpmを取得できるのは、ネットワークが繋がらない環境でインストールを行いたい場合等に便利そう。

ErlangでUNIXドメインソケットのクライアント接続を行なう簡単な方法

Erlang(OTP-17.3)では標準でUNIXドメインソケットをサポートされておらず、ちゃんと使おうとすると外部ライブラリが必要だったり、自前でポートドライバを書く必要があったりして、結構面倒。

ただ、特に性能等を気にせず簡単に使いたいだけなら、ncコマンド(netcat)がクライアント機能を持っているので、単にそれをラップすれば良い。

ncコマンドでのUNIXドメインソケット使用方法

-Uオプションを付けることで、UNIXドメインソケットが扱えるようになる。

サーバ:

# ※ 一つ以上のクライアントは接続不可
$ nc -U -l /tmp/hoge.socket

クライアント:

$ nc -U /tmp/hoge.socket

サーバとクライアントの通信は標準入出力経由で行なう。 

# サーバに"Hello World\n"とデータを送る
$ echo "Hello World\n" | nc -U /tmp/hoge.socket

Erlangから使う方法

erlang:open_port/2でncコマンドを呼び出すだけ。

-module(unix_socket).

-export([connect/1, send/2, close/1]).

%% @doc UNIXドメインソケット用のクライアント接続関数
-spec connect(string()) -> {ok, port()} | {error, Reason::term()}.
connect(UnixDomainSocketPath) ->
    %% open_port/2を使って、ncコマンドを呼び出す
    Command = "/bin/nc",
    Port = erlang:open_port({spawn_executable, Command},
                            [{args, ["-U", UnixDomainSocketPath]},
                             stderr_to_stdout, binary, exit_status]),
    receive
        %% 50ms以内にコマンドが停止したら、connect失敗扱いにする
        {Port, {exit_status, Status}} ->
            receive
                {Port, {data, ExitReason}} ->
                    {error, {abort, Command, [{status, Status}, {reason, ExitReason}]}}
            after 0 ->
                    {error, {abort, Command, [{status, Status}]}}
            end
    after 50 ->
            %% 接続成功
            {ok, Port}
    end.

-spec send(port(), iodata()) -> ok | {error, Reason::term()}.
send(Port, Data) ->
    try
        _ = erlang:port_command(Port, Data),
        ok
    catch
        error:Reason ->
            {error, Reason}
    end.

-spec close(port()) -> ok.
close(Port) ->
    erlang:port_close(Port).

使用例:

%% 事前に別のシェルで`nc -U -l /tmp/hoge.socket`が実行されているものとする

%% 接続失敗: 存在しないパスを指定
> unix_socket:connect("/tmp/fuga.socket").
{error,{abort,"/bin/nc",
              [{status,1},
               {reason,<<"nc: unix connect failed: No such file or directory\n">>}]}}

%% 接続成功
> {ok, S} = unix_socket:connect("/tmp/hoge.socket").
{ok,#Port<0.23824>}

%% データ送信
> unix_socket:send(S, <<"Hello\n">>). % サーバ側の端末に"Hello\n"と表示される
ok

%% データ受信:
%%   サーバ側の端末で"World\n"という文字列が入力されたものとする
> flush().
Shell got {#Port<0.23824>,{data,<<"World\n">>}}
ok

%% 切断
> unix_socket:close(S).
ok

デバッグ用途等であれば使えなくはない、程度のメモ書き。