mojavy.com

ptraceを駆使してscreenifyっぽいことをするreptyrがすごい

July 12, 2013 at 07:15 PM | categories: C, linux |

reptyrというおもしろいものをみつけたのでご紹介

reptyr とは

reptyrとは"re-ptying"するためのプログラムで、起動中のプロセスを新しい別のターミナルにもってくることができます。 例えば、うっかりscreenやtmuxの外で起動してしまった長い時間のかかるバッチ処理を、起動したままscreenの中にもってくることができます。

https://github.com/nelhage/reptyr

使い方

$ reptyr PID

現在のターミナル内にもってきたいプロセスのpidを引数にします。 attach後は、そのプロセスの入出力は^Cや^Zも含めて新しいターミナル側を向きます。

それscreenifyでできるよ

screenifyと呼ばれるスクリプトが昔からあって、それはgdbつかって似たようなことをやってるらしいです。 でもreptyrならもっとうまくできます。

例えば従来のscreenifyには以下のような問題がありました。

  • screenifyでattachしたプロセスは、元のターミナルから入力をうけつけてしまう
  • ncursesをつかってるプログラムをscreenifyすると、そのプログラムはwindowのリサイズがとれなくなる
  • screenifyした新しいターミナルでは^Cがきかない

reptyrはこういった問題を全部解決できます。

移植性

reptyrは対象プロセスを操作するのにptraceをつかっているのでLinuxに強く依存しており、Linuxだけをサポートしています。 SolarisやBSDに移植することも技術的には可能ですが、現状はプラットフォーム固有の部分を抽象化するようにはデザインされていないようです。

reptyrは現状ではi386, x86_64, ARMをサポートしています。他のアーキテクチャへの対応はarch以下に対応コードを追加すれば比較的容易です。

ptrace_scope on Ubuntu Maverick and up

Ubuntu Maverick以降ではptraceの機能がデフォルトで無効になっています。 以下コマンドで一時的に有効にできます。

$ echo 0 > /proc/sys/kernel/yama/ptrace_scope

rootで/etc/sysctl.d/10-ptrace.confを編集すると永続的に変更できます。またptrace_scopeに関する詳細な説明もここに書いてあります。

どうやってるの?

ソースを追ってみたところ以下のような処理をしているようです。

  1. reptyrプロセス側でptyをつくる
  2. attach対象のプロセスのttyのtermios設定をptyにコピーする
  3. ptraceで対象プロセスをattachしてレジスタ内容を一旦退避
  4. attachしたプロセス側でmmapし、そこにreptyrプロセス側でつくったptyをコピー
  5. attachしたプロセス側でコピーしたptyをopenし、setsid〜ioctlでそこに制御端末を割り当てる
  6. attachしたプロセス側でdup2して入出力をttyに向ける
  7. レジスタ内容を復元、後始末してptraceをdetach

reptyrのキモは5の制御端末をptyに割り当てるところで、これをすることによって従来のscreenifyの問題が回避できます。

しかし、単にioctlTIOCSCTTYするだけではうまくいかないのでちょっとしたトリックが必要です。詳細はhttp://blog.nelhage.com/2011/02/changing-ctty/ に解説があります。 reptyrの作者は自力でこの方法を思いついたそうですが、同様のテクニックは injcodeneercs でも使用されているそうです。

reptyrってどう読むの?

repeaterのように発音してもいいけど曖昧なのでre-P-T-Y-er (たぶんリ・ピーティーワイアー)のように発音してもよいそうです。

制約

  • backgroundにしたときは前のターミナルでbgやfgを実行する必要があります。background制御はshellがやっているので、これを直すにはshell側に手をいれる必要があります。
  • 現状では子プロセスがあるプロセスはattachできません

類似のもの

参考

まとめ

reptyrは1000行くらいの小さなプログラムですが、なかなかおもしろいハックだと思うので興味がある方はソースを読んでみて下さい。



pythonのswigエクステンションからdebian packageをつくる手順メモ

February 27, 2013 at 11:46 PM | categories: python, debian, linux |

debian

注: 以下は古めの環境(Lenny or Squeeze)と古めのpython (2.5 or 2.6)をターゲットにしたときの手順なので、最新の環境では別な方法があるかもしれません。

目次

1. 必要なパッケージをインストール

  • python-setuptools
  • python-all-dev
  • python-support
  • python-stdeb
  • swig
  • debhelper
  • devscripts
  • dh_make

たぶんこれだけあれば大丈夫。(python-supportはdeprecatedらしいけどここでは無視)

2. setup.pyをかく

apt-get source python-xxxで適当なパッケージのソースをダウンロードして参考にするとよい

以下例

#!/usr/bin/python

from setuptools import setup, Extension

__version__ = "0.0.1"

setup(name         = "yourext",
      version      = __version__,
      author       = "Your Name",
      author_email = "[email protected],
      url          = "http://example.com/python-yourext",
      download_url = "http://example.com/python-yourext-%s.tgz" % __version__,
      description  = "yourext client library for python",
      long_description = open('README.md').read(),
      license      = "LGPL",
      platforms    = ["Platform Independent"],
      classifiers  = [
        "Development Status :: 5 - Production/Stable",
        "Intended Audience :: Developers",
        "License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
        "Operating System :: OS Independent",
        "Programming Language :: Python",
        "Topic :: Software Development :: Libraries :: Python Modules"
      ],
      ext_modules  = [
        Extension(name='yourext',
                  sources=['path_to_swig/yourext.i'],
                  include_dirs=['path_to_lib/include'],
                  library_dirs=['path_to_lib/lib'],
                  libraries=['yourlibrary'],
                  define_macros=[(FOO_BAR, 123), (DEBUG, None)],
                  extra_compile_args=['-std=gnu99', '-Wextra'],
                  )
      ],
      py_modules = ['pure_python_module_name', 'foo.bar'],
      include_dirs = [''],
)
  • ext_modulesの中にExtensionをかく
    • Extension.sources にはswigの定義ファイルを直接指定できる
    • Extension.include_dirs, Extension.library_dirs, Extension.librariesはそれぞれgccでいう-I, -L, -lの値
    • Extension.define_macrosはタプルで渡す。上の例だと -DFOO_BAR=123 -DDEBUG の意味
    • Extension.extra_compile_args はその他のコンパイルオプション
  • platforms, classifiersの内容はpython-cjsonあたりからコピーした
  • pure pythonの部分はpy_modulesにモジュール名を列挙する。パスではない
  • swigが生成した.pyファイルをpy_modulesに含める汎用的な方法は見つからなかった。(必要な場合はスクリプトでinclude_dirsにコピーすることで対応できる)
  • 3. ビルド確認

    以下コマンドでpython extのビルドを確認する。成功すると、buildディレクトリ以下に共有ライブラリが生成される

    python setup.py build

    4. debianizeする

    以下コマンドでdebianパッケージに必要なファイルを生成する。このときegg-info等も生成される

    python setup.py --command-package=stdeb.command debianize --force-buildsystem=True

    5. debをつくる

    debuild -uc -us

    -uc -usは署名を省略するためのオプション。

    成功すると、親ディレクトリにdebファイルができてるはず

    その他ツール等

    • dupload: リポジトリにアップロードするためのもの
    • dlocate: dlocate -S filename のようにすればそのファイルを含むパッケージを調べることができる
    • cdbs: debianパッケージを作成するための別なやりかた(?)。 ちゃんとしらべてない


    おやつの時間をお知らせしてくれるUnixコマンド:at teatime (他...)

    January 08, 2013 at 08:30 PM | categories: unix, tips, linux |

    banana

    Favorite Linux Commands(http://clippy.in/b/YJLM9W) で紹介されてたコマンドのうち知らなかったものをメモ。

    at

    入力されたコマンドを指定されたタイミングで実行するようにスケジュールする。 cronに登録するほどでもない単発のコマンドを実行したいときとかにつかう。 時間の指定には現在の時刻からの経過時間や絶対時間の他にteatimeやmidnightといった文字列もつかえる。 ちなみにteatimeは午後4時。 出力先を指定しなければコマンドの出力はcronと同じようにメールにとぶ。$TTYにリダイレクトしてやればコマンドを実行した端末に表示させることもできる。

    echo "echo おやつの時間です > $TTY"| at teatime
    echo "echo はろー > $TTY" | at now + 3 minute
    

    mtr

    tracerouteとpingをあわせたようなもの。tracerouteより表示がみやすい。 ネットワークのどこで時間がかかってるのか一目でわかる。

    mtr mojavy.com
    

    column

    入力テキストをいい感じのカラム表示にフォーマットしてくれる。 縦に長い出力するコマンドとか、そのままだと出力がみづらいときとかにつかう。

    gem list | column
    mount | column -t
    grep -v '^#' /etc/apt/sources.list | column -t
    

    reset

    端末をリセットする。 うっかりバイナリファイルをcatとかしてしまって端末が壊れてしまった場合に端末を閉じずに復帰できる。

    sshfs

    ssh経由でリモートのファイルシステムをマウントできる。

    sshfs name@server:/path/to/dir /path/to/mount/point
    fusermount -u /path/to/mount/point  # unmount
    

    その他

    以下はコマンド自体の機能ではないけど覚えておくと便利かもしれないもの

    curl ifconfig.me

    ifconfig.meというサイトがある。自分のグローバルIPがわかる。

    dig +short txt .wp.dg.cx

    dnsクエリでwikipediaのエントリーがみれる。

    $ dig +short txt banana.wp.dg.cx
    "Banana is the common name for herbaceous plants of the genus Musa and for the fruit they produce. It is one of the oldest cultivated plants. They are native to tropical South and Southeast Asia, and are likely to have been first domesticated in Papua New " "Guinea. Today, they are cultivated throughout the tropics. They are grown in at least 107 countries, primarily for their... http://en.wikipedia.org/wiki/Banana"
    


    pacoを導入

    October 16, 2012 at 06:30 PM | categories: paco, linux |

    今さらだけどpacoを導入した。

    http://sourceforge.net/projects/paco/files/paco/2.0.9/ から最新のパッケージをダウンロード、展開して以下コマンドでインストール。gpacoは使わないと思うので--disable-gpacoした。

    ./configure --disable-gpaco
    make && sudo make install
    sudo make logme
    

    何かをインストールする際は以下のようにする。

    sudo paco -D make install
    

    make install の部分は、bash install.shとかなんでもいい。

    参考



    About Me

    pic
    mojavy

    Recent posts






    Categories



    Badges