MOSA Multi-OS Software Artists

MOSAはソフトウェア開発者を支援します

プログラマーに興味がある方なら誰でも入会いただけます。
MOSA Multi-OS Software Artists
===SINCE 1995===

  • iPhone/iPod touch アプリ紹介
  • MOSA掲示板
  • 活動履歴
  • About MOSA(English)

MOSADenバックナンバー 2009年5月発行分

  • MOSA Developer News[MOSADeN=モサ伝]第344号

    2009-05-26 

    目次

    • 「Wonderful Server Life」    第93回   田畑 英和
    • 小池邦人のCarbon視点でiPhone探求
    • ターミナルの向こうから      第48回  海上 忍 

    「Wonderful Server Life」  第93回  田畑 英和

    〜「Deployment」編〜

     Mac OS XおよびMac OS X Serverのアップデートの最新版10.5.7がリリースされました。いつものように直前のバージョンからのデルタアップデートと、10.5.0からのコンボアップデートがそれぞれソフトウェア・アップデートで配布されています。

    ・Mac OS X 10.5.7 Updateについて
    http://support.apple.com/kb/HT3397?viewlocale=ja_JP
    ・Mac OS X Server 10.5.7について
    http://support.apple.com/kb/HT3398?viewlocale=ja_JP

     前回はNetBootのシステムイメージを作成するところまで解説しましたので、今回はその続きのNetBootサービスの設定について解説します。

    ◇関連サービス
     システムのイメージ作成が完了すれば、この後のサービスの設定はさほど難しくはありません。ほとんどデフォルトの設定だけでもNetBootを起動させることはできます。ただし注意が必要なのは、NetBootは他のサービスと連携して動作しますので、システム全体としての準備が適切に行われている必要があります。
     まずはNetBoot以外に必要となるサービスの確認をしておきましょう。まずDHCPが必要になります。これはNetBootクライアントがDHCPを使ってIPアドレスを取得するためです。ですので、NetBootが機能するにはDHCPによってIPアドレスが提供されている環境である必要があります。
     次にNetBootのシステムイメージを提供するために、NFSもしくはHTTPが必要になります。NFSのほうがパフォーマンスに優れていますので、通常はNFSを使用します。NFSですが、NFSの共有ポイントは自動的に作成され、サービスも自動的に開始します。
     あとはAFPが必要になる場合があります。これは設定によって状況が変わりますのでまた後ほど説明することにしましょう。というわけでNetBootを使用するには以下の関連するサービスが必要になります。

    ・NetBootで必要となる関連サービス
      DHCP(必須)
      NFS(またはHTTP)
      AFP(必要に応じて)

    ◇NetBootサービスの設定
     さていよいよNetBootサービスの設定です。「サーバ管理」を使ってサーバに接続し、まずはNetBootサービスの「一般」の設定を行います。前回の設定ですでにイメージの保存場所は設定しました。あとはNetBootサービスを提供するポートの設定を行います。ここではEthernetを選択します。
     イメージの保存場所をすでに設定した方はもう気付いているかと思いますが、ポートをなにも選択しないでNetBootサービスを設定しようとすると警告が表示されます。デフォルトではなにもポートが選択されていませんので、ポートの設定を忘れないようにしましょう。

    ・ポートの設定
    http://www.htabata.com/img/MXS105/netboot/nb_admin_01.png

     次に「イメージ」の設定です。「イメージ」の設定画面を表示すると「システムイメージユーティリティ」で作成したイメージがリストに表示されます。
    1台のサーバで最大25個のイメージを管理できます。デフォルトで使用するイメージの「デフォルト」をチェックします。
     「ディスクレス」の設定がありますが、この設定はNetBootクライアントの挙動を理解しておく必要があります。NetBoot起動したクライアントはシステムを直接変更することはせず、なにかデータに変更があればシャドウファイルと呼ばれるファイルに保存します。イメージの設定でディスクレスを有効にした場合はこのシャドウファイルはサーバ上に保存されます。このときデータの転送にはAFPを使用しますので、ディスクレスでNetBootを運用する場合にはAFPサービスが必要になります。ディスクレスが無効な場合、シャドウファイルはクライアントのハードディスクに保存されます。

    ・イメージの設定
    http://www.htabata.com/img/MXS105/netboot/nb_admin_02.png

     シャドウファイルですがクライアントを再起動するとその内容は破棄されます。ですのでNetBootでは再起動するたびにシステムが最初の状態に戻るようになっています。つまりシステムの内容を常に一定の状態に保つ事ができるわけです。
     イメージをNFSではなくHTTPで提供したい場合には「プトロコル」の設定を行います。

     特定のクライアントのみNetBootしたい場合は「フィルタ」の設定を行います。フィルタの設定ではMACアドレスを指定することにより、特定のクライアントのみにNetBootサービスを許可することができます。逆に特定のクライアントへのNetBootサービスの提供を拒否するように設定することもできます。
     フィルタはイメージごとに設定することもでき、この場合はMACアドレスだけではなく機種別のフィルタも設定することができます。例えばイメージが特定の機種に依存しているような場合は、そのイメージで起動可能なクライアントを制限することができます。

     以上がNetBootサービスの設定になります。あとはサービスを開始しどこにも問題がなければクライアントをNetBoot起動できるようになります。それでは次回はクライアントのNetBoot起動について解説します。
                                 次回へつづく

    小池邦人のCarbon視点でiPhone探求(2009/05/22)

    〜 ウィンドウの代役を用意する 〜

    さて、取り込んだ画像をファイルへ保存し、そのパス名をモデルオブジェクトへ登録する準備が整いました。今回からは、UIViewController上に配置したUITableViewにそうした画像を一覧表示させる処理へと話を進めたいと思います。

    ところで、アプリケーションの起動時と終了時に処理すべき事項として「環境設定」の読み込みと保存があります。これについては、実際に何らかの環境設定用パラメータが必要となった時点で解説したいと考えています。iPhone OSには、アプリケーションの環境設定をiPhoneの「設定」アプリで管理する方法もあるのですが、本アプリケーションではそちらの手法は使わない予定です。
    後は、加速度センサー(アクセロメータ)やCore Location(GPSによるデバイス位置の確認)のデリゲートメソッドの実装等もアプリケーション起動時に行うと良いのですが、こちらはiPhone 3.0で何か面白い動きがあるかもしれませんので、その正式登場まで待ちたいと思います(笑)。

    iPhone用アプリケーションの開発には、AppKitをUIKitに差し替えたCocoa Frameworkを利用します。そこで採用されているGUI(グラフィカル・ユーザインターフェース)については、ビュー(UIView)やそのサブクラスであるコントロール(UIControl)を活用するなど、Mac OS Xのそれと多くの共通点がありますが、メニューが存在しないなど異なる点も幾つか見受けられます。ま
    た、UIKitにはAppKitには存在しない固有なクラスもあり、その有効活用こそがiPhoneアプリケーションの出来映えを左右すると言っても過言ではありません。そのしたクラスの代表選手が、UIViewControllerを始めとするビューコントローラです。

    UIViewControllerは、その名の通りUIViewのコントローラとして働くためにUIKitに追加されています。UIViewControllerはUIResponderクラスを継承しており、自身が管理しているUIView上で発生した「マルチタッチ・イベント」を受け取り処理することが可能です。iPhoneアプリケーションでは、ある目的を実現するための作業単位を、ひとつのビューコントローラに結びつけて設計す
    るのが普通です。ちなみに、Mac OS Xのアプリケーションにおける作業単位は、間違いなくウィンドウ(ダイアログやフローティングウィンドウも含む)です。

    アプリケーションの目的を達成するには、新規ウィンドウをオープンし、そこにフォーカスを当てることでユーザの作業を促します。また、ウィンドウには目的に応じた色々なビューやコントロールが配置されることになります。
    iPhoneアプリケーションの場合には、AppKitのNSWindowとNSWindowControllerの組み合わせが、UIKitのUIViewとUIViewControllerに相当すると考えればよいでしょう。ちなみに、iPhoneでもウィンドウ(UIWndow)は存在しますが、
    こちらはUIViewのサブクラスであり(Mac OS Xの場合と異なる)スクリーン上にひとつだけ配置されます。こうした唯一のウィンドウはmakeKeyWindowメソッドでキーウィンドウ(Mac OS Xだとフロントウィンドウ)に指定され、ユーザからのタッチイベントを受け付け始めます。

    まあ、複数のウィンドウを用意してもかまいませんが、通常のiPhoneアプリケーションでは代わりに複数のビューコントローラを用意します。
    UIViewControllerには、それ自身が管理するUIViewがひとつだけ付属しています。このUIViewがUIWindowのサブビューとなりスクリーン全面に表示されるわけです。つまり、ウィンドウを切り替えるのではなく、UIViewControllerとUIViewのペアを切り替えることにより、ユーザを目的の機能にフォーカスさせます。UIKitには、UIViewControllerのサブクラスとして機能が拡張された
    「UITableViewController」「UINavigationController」「UITabBarController」の3つのビューコントローラが用意されています。

    ・UIViewControllerとUITableViewController

    UIViewControllerは一般的に使われるビューコントローラです。Xcodeの「View-Based Application」テンプレート(雛形)でプロジェクトを作成すると、MainWindow.xibにUIViewControllerのサブクラスが登録され、その機能を実装するためのソースコードが用意されています。UIViewControllerで使われるUIViewは、別のnibファイルに保存されており、それがアプリケーション起
    動時にスクリーン全体に表示されることになります。もう片方のUITableViewControllerは、リスト表示のためのUITableView(UIViewのサブクラス)をうまく管理できるよう機能拡張されています。

    ・UINavigationController

    UINavigationControllerは、複数のビューコントローラを管理するためのスタックを保持しています。スタックに対しビューコントローラをプッシュやポップすることで、複数のUIViewControllerやUITableViewControllerを効率よく切り替えて使えます。Mac OS Xで言うなら、階層化されたウィンドウを目的に応じて切り替えながら作業を進めるタイプのアプリケーションと似ていま
    す。

    UINavigationController   |--- UITableViewController 
                            |--- UITableViewController
                            |--- UIViewController
                            |--- UIViewController
    

    Xcodeの「Navigation-Based Application」テンプレートのMainWindow.xibには、ひとつのUINavigationControllerが登録されています。
    UINavigationControllerの管理対象としてUIViewControllerのサブクラスであるRootViewControllerがひとつだけ用意されています。RootViewControllerはRootViewController.xibに用意されており、そのクラス自体はソースコードで実装されています。 ビューコントローラを追加することで、どんどん機能を拡張することが可能です。

    ・UITabBarController

    UITabBarControllerを使うと、複数のUIViewControllerやUITableViewControllerを並列で管理できます。タブ切り替えで目的の機能を使えるようにするわけです。Mac OS Xであれば、NSTabViewで対象ビューを切り替えるのと似ていますが、それよりもどちらかと言えば、多数のウィンドウを作業毎に切り替えて使う感じに近いかもしれません。

    UITabBarController   |--- UITableViewController 
                        |--- UIViewController
                        |--- UINavigationController  |--- UITableViewController
                                                     |--- UITableViewController
                                                     |--- UIViewController
    
    

    Xcodeの「Tab Bar Application」テンプレートのMainWindow.xibには、タブ数が2に設定されたUITabBarControllerが登録されています。ひとつ目のタブをタップして表示される内容は、FirstViewControllerクラスとしてソースコードで実装されており、ふたつ目のタブで表示されるUIViewControllerの方は、SecondView.xibの方に用意されています。ユーザがタップ可能なタブ数を増や
    していけば、さらに多くのビューコントローラを管理することが可能となります。

    以前にも解説しましたが、Xcodeのプロジェクトをテンプレートから作る場合、適切なビューコントローラを活用するためには、目的に応じて「View-Based Application」か「Navigation-Based Application」か「Tab Bar Application」のどれかを選びます。どれを選択するかについては色々な要因があると思いますが、上記ビューコントローラの相関図を見ると、最も注目すべき要因はアプリケーションの規模(機能の複雑さ)なのかもしれません。

    本アプリケーションは「Navigation-Based Application」テンプレートを使用しています。次回は、このテンプレートの内容を解説してから、UINavigationControllerが管理する(アプリでUIViewが最初に表示される)UITableViewControllerのサブクラス実装の話へと移りましょう。

    ターミナルの向こうから      第48回  海上 忍

    〜 リモートでシェルを使う(3) 〜

    ・SSHの「鍵ペア」とは

     SSHでは、あらかじめ「鍵ペア」を作成してサーバ/クライアント双方に登録しておくと、パスワードの入力を省くことができます。鍵ペアを登録しないかぎり、セッションの都度パスワードを入力しなければならないため、特にscpコマンドでファイルコピーを行う場合には作業が繁雑になります。
     鍵ペアは、「秘密鍵」と「公開鍵」の一対で構成されます。公開鍵はデータストリームを暗号化処理するときに利用され、その公開鍵と対をなす秘密鍵でのみ暗号を解く(復号化)ことができます。公開鍵は暗号化処理する目的のみ、秘密鍵は対をなす公開鍵で暗号化されたデータストリームを復号化する目的のみで利用されます。ペアで利用しないかぎり意味がない鍵、というわけです。
     この鍵ペアには、高度な暗号化処理が施されます。Leopard(Mac OS X 10.5.7)の場合、SSH2に対応したOpenSSH_5.1p1が収録されているので、暗号化形式としてRSAとDSAを選択できます。現在利用されているSSHのバージョンと暗号化形式の組み合わせは、SSH1とRSA、SSH2とDSA、SSH2とRSAの3通りが存在しますが、DSA鍵のほうがは署名を偽造しやすい(実際には気が遠くなるほどの計算量が必要なはずですが)といわれることから、ここではSSH2とRSAの組み合わせを前提に、解説を進めることにします。

    ・鍵ペアを作成する
     鍵ペアの作成には、「ssh-keygen」コマンドを実行します。RSA形式の鍵ペアを作成する場合、ターミナルから以下のとおりコマンドを実行します。なお、OpenSSH_5.1p1の初期値では、鍵の長さは2,048ビットに設定されています。

    - - - - -
    $ ssh-keygen -t rsa
    - - - - -

     すると、鍵ペアを保存するディレクトリの確認が行われます。デフォルト(~/.ssh)で問題なければ、そのまま「enter」を押します。

    - - - - -
    Generating public/private rsa key pair.
    Enter file in which to save the key (/Users/shinobu/.ssh/id_rsa):
    - - - - -

     続いて、パスフレーズを入力します。パスフレーズにはスペースやタブを利用できるので、一般的なパスワードよりも長い、他人に知られる可能性は低いが意味のある(記憶に残りやすい)文を使うことが推奨されています。同じパスフレーズを2度入力すれば、秘密鍵(id_rsa)と公開鍵(id_rsa.pub)の2つのファイルが、ホームフォルダ直下の「.ssh」フォルダ(Finderには非表示)に作成されます。

    - - - - -
    Enter passphrase (empty for no passphrase):
    Enter same passphrase again:
    Your identification has been saved in /Users/shinobu/.ssh/id_rsa.
    Your public key has been saved in /Users/shinobu/.ssh/id_rsa.pub.
    - - - - -

     このとき、フィンガープリントも表示されますが、とりあえずは必要ありません。コマンド「ssh-keygen -l」を実行して公開鍵の保存場所を示せば、後日確認することもできるため、メモを取らずに先へ進んでもかまいません。

    ・公開鍵をサーバへコピーする

     作成した鍵ペアのうち秘密鍵は手元のマシン(Mac)に、公開鍵はファイルコピーなどの方法で接続先(リモートサーバ)に転送して利用します。ここでは、仮にホームディレクトリにそのままのファイル名(id_rsa.pub)でコピーします。なお、入力するパスワードはサーバ側のもの(先ほどのパスフレーズは無関係)です。

    - - - - -
    $ scp ~/.ssh/id_rsa.pub yourname@dokka.com:~/
    yourname@dokka.com's password:
    - - - - -

     最後に、sshでサーバへログインし、コピーした公開鍵を所定のディレクトリへコピーしたあと、以下のコマンドラインを実行して適切なファイルパーミッションを設定します。これで一般的なUNIX系OSならば作業は完了ですが、Mac OS X Leopardの場合には、もうひと手間が必要です。

    - - - - -
    $ ssh yourname@dokka.com
    Password:
    yourname@dokka:~> mkdir .ssh
    yourname@dokka:~> chmod 700 .ssh
    yourname@dokka:~> cat id_rsa.pub >> .ssh/authorized_keys
    yourname@dokka:~> cat id_rsa.pub >> .ssh/authorized_keys2
    yourname@dokka:~> chmod 600 .ssh/*
    - - - - -

    ・最後におまじない

     Mac OS Xに収録のOpenSSHには、キーチェーンと連動するための機能が追加されています。通常は、前述の作業だけでパスワードなしにSSHを利用できるようになりますが、Leopardは以下のコマンドを実行しないかぎり、キーチェーンへの登録をうながすダイアログが表示され続けます。コマンド実行後、「ssh yourname@servername」とコマンドを実行してパスワードを求められなければ、すべての作業は完了です。同様に、scpコマンドがパスワードなしで通ることも確認しておきましょう。

    - - - - -
    $ ssh-add -K
    Enter passphrase for /Users/shinobu/.ssh/id_rsa:
    Passphrase stored in keychain: /Users/shinobu/.ssh/id_rsa
    Identity added: /Users/shinobu/.ssh/id_rsa (/Users/shinobu/.ssh/id_rsa)
    - - - - -

    ◇MOSAからのお知らせと編集後記は割愛します◇

     

     MOSA Developer News   略称[MOSADeN=モサ伝]
            配信停止 mailto:mosaden-ml@mosa.gr.jp
     記事内容に関するご意見 mailto:mosaden-toukou@mosa.gr.jp
          記事投稿受付 http://www.mosa.gr.jp/?page_id=850
    Apple、Mac OSは米国アップル社の登録商標です。またそのほかの各製品名等
    はそれぞれ各社の商標ならびに登録商標です。
    このメールの再配信、および掲載された記事の無断転載を禁じます。
    特定非営利活動法人MOSA  http://www.mosa.gr.jp/
    Copyright (C)2009 MOSA. All rights reserved.

  • MOSA Developer News[MOSADeN=モサ伝]第343号

    2009-05-19 

    目次

    • りんご味Ruby         第47回  藤本 尚邦
    • 藤本裕之のプログラミング夜話   #160
    • 高橋真人の「プログラミング指南」  第158回

    りんご味Ruby   第47回  藤本 尚邦

    引き続き、Ruby+RubyCocoaを使って「CoreGraphicsによるPDFの描画」を記述するための簡易言語(DSL)についてです。

    beginPage と endPage は、何らかのプログラム片を挟んで、順番に呼ぶことを前提として用意されたメソッド(CoreGraphics の API)です。前回は、この2つのメソッドの組み合わせを page という1つのメソッドにまとめました。その肝となるのはブロック構文です。今回はちょっと脱線して、そのブロック構文のメリットや使いどころなどについて考えてみることにします。

    CGContextBeginPage のリファレンスマニュアルには:

    you should call this function together with CGContextEndPage …

    とあります。「あなた(プログラマ)は2つのAPIを一緒に使うべきだ」というわけです。とはいっても CGContextEndPage を忘れてしまうかもしれませんし、実際のところ、このルールが守られるかどうかはプログラマに委ねられています。その上、(使うべき) CGContextEndPage を使わなかったとしても、コンパイルやリンクでエラーになるわけではありません。プログラムを実行してみて
    初めて何かおかしいと気づくことになるでしょう。あるいは気づかずにそのままになっているかもしれません。

    そんなことなら、一緒に使うことを強制するようなAPIを用意した方がよさそうなところですが、実際にはそのようなAPIがないのは、(残念ながら) C にしても Objective-C にしても、任意のプログラム片をデータとして扱う手段が弱いからでしょう(ないわけではないのですが)。

    任意のプログラム片をデータとして扱うことができることにより、その「任意のプログラム片」を仮引数(以下の例ではblockという名前です)として受け取る:

     def page(&block)
       beginPage
       block.call(self)
       endPage
     end
    

    というようなメソッドを定義することが可能になります。このようなメソッド(あるいは関数)自体は、C や Objecive-C でも定義することはできます:

     void CGContextPageDo(CGContextRef context, void (* block)(CGContextRef))
     {
       CGContextBeginPage(context);
       block(context);
       CGContextEndPage(context);
     }
    

    しかし、違いが出てくるのは呼び出し時の使い勝手です。上記の C言語バージョンのpageを呼び出す場合は、その都度 block に渡す関数を定義することになるでしょう:

     static void draw_page_1(CGContextRef context) {
       CGContextSetRGBFillColor(context, 1.0, 0.0, 0.0, 1.0);
       CGContextAddArc(context, 300, 300, 100, 0, 2 * 3.14, 1);
       CGContextFillPath(context);
     }
     /* ... 中略 ... */
     CGContextPageDo(context, draw_page_1);
    

    この draw_page_1 みたいな使い捨てに近い関数は、どんな名前をつけるべきかということを考えるだけでもちょっと困ってしまいます。結局は、このようなAPIがあっても使うのが面倒くさいので、自力で beginPage と endPage で挟む方法を選択することになりそうです(そしていずれ endPage を書き忘れます)。

    2つのAPIを1つにまとめたメリット(endPageが呼ばれることを保証する)を保ったまま、この面倒くささをなくすのにうってつけなのが、Rubyの場合はブロック構文なのです。付け加えると、JavaScriptならば関数リテラルで、Lisp系言語ならばラムダ式です。これらはみな、その場限りのプログラム片(無名の手続き) をデータとして扱うための手段という意味では似たようなものです。

    すでに見てきているようにRubyのブロック構文を使うと、C言語の例でdraw_page_1 として定義した部分をブロックにして:

     pdf.page do 
       pdf.setRGBFillColor(1.0, 0.0, 0.0, 1.0)
       pdf.addArc(300, 300, 100, 0, 2 * Math::PI, 1)
       pdf.fillPath
     end
    

    のように書くことができます。2つのAPIをまとめるメリット自体は明らかだと思うので、使い勝手が十分であればこのようなAPIがあればその方がいいですよね。このパターンにはまるAPIやクラス(例えばNSAutoreleasePool)は多いので、Objecitve-Cも、さらに構文を拡張するのならブロック構文は入れてほしいところです。

    次回は、CGPDFContext.file を実装して、簡易PDF描画言語DSLをどうにか完成させる予定です。

    藤本裕之のプログラミング夜話 #160

     ゴールデンウイークのせいで一週余計に間隔があいたこともあるし、ここで一度、寄り道の多かったこの1月からの話を整理してみたい。

     1月、年末年始に列島を吹き荒れた派遣切りの風にあおられつつ(かっこいいな、表現が小説みたいである)不祥フジモトが考えたのは、そういえば我々プログラマを含む「ソフトウェア技術者」というヤツは、80年代に施行された最初の「労働者派遣法」のときから「高度で専門的な知識と経験を要する職業」として、その対象だったんだよな、ということであった。

     その後、派遣法は幾度か改正(なにが改「正」だという意見はあろうが、一応そういう用語なので)され、みなさんご案内の通り「企業がいつでもクビにできる安価な労働力を調達するための便利な法律」に変質し、いままさに「派遣切り」「格差拡大」などの問題を生み出しているわけである。

     が、派遣法がそうなった……つまり当初の「高度で専門的な知識と経験を要する職業」からその対象を拡大したからと言って、「ソフトウェア技術者」が「高度で専門的な知識と経験を要する職業」でなくなったわけではないのに……ないよね? なのになんでまたこうも「ソフトウエア技術者」が食えなくなってきてるんだろうか?

     え? 「オレは食えてる」って? そりゃオレだってなんとか仕事はあって今日明日ホームレスになりますってわけぢゃないが、それでもタカハシ編集長が本稿のテーマとして「アプリケーション・プログラマは絶滅に瀕しているのか」というのをオレに示し、オレの方でもなるほどその問題について考えてみましょうかと思って不思議でないくらいの「そういう雰囲気」ってのは共有されているではないか。いない?

     もちろん「♪好景気を知らない子供達」だったりする今の若い人は「♪青空が好きで花びらが好きでなんとか食えてりゃ充分ぢゃないですか」と言うかもしれないが、「なんとか食えてる」のと「景気がいい」のは違うんであり、オレはたまたま(自業自得という意見もある)そうなってないが、オレ達が20代、30代だったときには、ほとんどのヒトが「普通の将来」として「結婚して子供の2人も作っていずれはマイホームも」てなことを想像していたし実現したヒトもいたのだよ。今の20代でそんな将来を確信できるヒトってどんだけいる?

     でね、世の中全般はともかく、ソフトウエア技術者に限って言うとそれはヘンぢゃないか、と。

     そりゃ我々のシゴトだって(バブルが弾けた話のときに書いたように)景気の悪さと無縁ではないが、でもなんか理論値・計算値以上に割を食わされているような気がする。いくら百年に一度の不景気(この「百年に一度」というキャッチはまったく根拠不明だよな……だってまだ大恐慌のときみたいにマンハッタンのビルからヒトが降ってないぢゃん、ねぇ?)とは言え、コンピュータリゼーションはその進行を止めたわけではないし、インターネットは隆盛だ。技術者の需要は拡大こそすれ縮小しているとは思えない。

     なのにあなたは京都へ行く……ぢゃない(そもそも古すぎだよな、このギャグ)、なのにその「繁栄」の果実は我々のところに落ちてこない。ここ10年くらいの間、幾人もの「IT社長」がその栄華を誇り、芸能人と浮き名を流し、国会議員に立候補したり逮捕されたりしたが(いや、逮捕はされたくないけどさ)、オレの知る限り一人たりとも「現役のエンジニア、プログラマ」ではなかった。昔、少しはHTMLとか書いたコトのあるヤツはいたかもしれないけど、基本的には「経営者」であり「マネージャー」なんだよね。

     彼らは儲けるがオレたちはそーでもない。いや、却って苦しくなったりしてる。

     これってなんだか俺たちのアズカリシラヌところで、さっき「そんなことあるわけないぢゃん」と否定したトコロの「『ソフトウェア技術者』が『高度で専門的な知識と経験を要する職業』でなくなる」という怪現象が、実際に起きてるみたいではないの? ではそれは、どこでどんな理由で起きてるのだろうか?
                           (以下次回 2009_05_15)

    高橋真人の「プログラミング指南」第158回

    これから始めようとする人へ(9)

     皆さんこんにちは、高橋真人です。
     さて、Cの基本的なメモリの確保と解放には、malloc()とfree()により行われるとお話ししましたが、Cocoaに使われるObjective-Cでは別にまた専用の仕組みが用意されています。
     Cocoaに限らず、オブジェクト指向のプログラミングでは、オブジェクトと言われるものの存在する場所として、メモリを動的に確保する必要が頻繁に発生しますから、ヒープ領域の利用は“日常的”です。
     Cocoaのコードを少しでも書いたことのある方なら、NSString *aStringとか、NSView *myViewというように、変数の名前の前に必ずアスタリスク(*)が必ず付くことはご存知でしょうし、このアスタリスクがポインタを表すこともCの経験があればお分かりですよね。
     ところで、Cにおいては構造体の変数を宣言する場合、静的に定義することは可能です。

    typedef struct {
       char  name[40];
       char  address[120];
       int   age;
    } Person;
    
    Person aPerson;
    
    strcpy(aPerson.name, "山田太郎");
    strcpy(aPerson.address, "東京都千代田区一番町1-1-1");
    aPerson.age = 25;
    

    といったような具合です。
     しかし、Objective-Cのクラスではそれはできません。クラスは形としては構造体の延長上にあるものですから、以下のように静的に宣言しようとすると、

    NSString myString;
    

    しっかりコンパイラにチェックされ、

    error: statically allocated instance of Objective-C class 'NSString'
    

    というように、許してもらえません。
     つまり、Objective-Cではクラスのインスタンスを宣言する場合には、必ず動的に行う必要があるわけです。

     さて、動的に定義された変数はそのままではオブジェクトを指していませんから、あらかじめ初期値としてnilを代入しておくか、その場で新規にオブジェクトを作成して代入するか、既存のオブジェクトを代入する必要があります。
     これをしない変数に対して何らかのメッセージを送ろうとすると、動作は不定、つまり、アプリはその時点で落ちることになります。
     ただ、nilが代入されている変数についてはこの限りではありません。この変数も「何のオブジェクトも指していない」ことには違いありませんが、これに対してメッセージを送っても、エラーにはなりません。「nilに対して送ったメッセージは単に無視される」ということがObjective-Cの言語として保証されているのです。そのため、変数の宣言をする場合には必ずnilを代入しておく、というのもひとつのやり方ではあります。

     さて、Objective-Cでオブジェクトを作成する場合には、例えば、

    NSString *myString = [[NSString alloc] initWithCString:"Hello"];
    

    などといったように、クラスに対してallocメッセージを送り、次いでinitないしそれに類するメッセージを送って初期化をするという流れになるのが普通です。見た目からも分かるように、このallocというメッセージによってヒープ領域からオブジェクトに必要な分量のメモリが確保されるわけです。
     このような、見た目にallocという文字があるものは、用が済んだら使い終わったメモリをきちんとヒープ領域に返さないといけません(ANSI Cのmalloc()とfree()と同様です。)。Objective-Cでは、この場合releaseというメッセージを送ります。
     自分でallocしたオブジェクトに対して使用後にきちんとreleaseを送らないと、メモリリークを招くことになります。

     ところで、オブジェクトを生成するメソッドの中に、allocを使っていないものがあります。例えば以下のようなケース。

    NSString *str1 = [[NSString alloc] initWithCString:"Hello"];
    NSString *str2 = [str1 stringByAppendingString:@" world!"];
    

     str1に対して、"Hello"という文字列を入れ、それに、" world!"という文字列を追加したオブジェクトを作って、str2に入れています。間違えないでいただきたいのは、str1とstr2は、それぞれ別のオブジェクトを示しているということです。

     NSLog(@"%@ - %@", str1, str2);
    

    とやってみれば、str1の中は依然として"Hello"のままであることが分かりますし、デバッガなどを使えば、str1とstr2の値が別のアドレス値であることも確認できると思います。
     ここのコードのポイントは、str1に対してstringByAppendingString:というメッセージを送ると、新たに別のオブジェクトが生成されるということです。

     さて、str1、str2ともに使い終わったら、使っていたメモリを解放する必要があります。str1の生成にはallocが使われていますから、当然

    [str1 release];
    

    とすればいいのですが、str2についてはどうなんでしょう?

     試しに、str2に対してもreleaseというメッセージを送ってみますと、どうなるでしょうか?
     何と、今度はアプリケーションは落ちてしまいます! 一体どうなっているのでしょう!?
     実は、ここではメモリリークの逆、つまり解放のし過ぎが起こっています。つまり、一度解放したメモリ領域に対して、再度解放のためのメッセージを送ってしまっているのです。ポインタ変数が保持しているアドレス値は、解放によって無効な値と化します。それに対して、再度何かの操作を行うと、プログラムはクラッシュしてしまうのです。

     ここで一つ疑問が湧きませんか?
     str2に対して、releaseを送ってはダメだとすると、このオブジェクトの後始末はいったいどのように行われているのだろうか、と。
     stringByAppendingString:メッセージによって、確かに新しいオブジェクトが作られてstr2に格納されているのに、releaseを呼ばなくてもちゃんとメモリの解放は行われるのでしょうか?

     この仕組みの裏には、「自動解放プール」という仕組みが働いています。次回はその辺をお話ししていきます。

    ◇MOSAからのお知らせと編集後記は割愛します◇

     

     MOSA Developer News   略称[MOSADeN=モサ伝]
            配信停止 mailto:mosaden-ml@mosa.gr.jp
     記事内容に関するご意見 mailto:mosaden-toukou@mosa.gr.jp
          記事投稿受付 http://www.mosa.gr.jp/?page_id=850
    Apple、Mac OSは米国アップル社の登録商標です。またそのほかの各製品名等
    はそれぞれ各社の商標ならびに登録商標です。
    このメールの再配信、および掲載された記事の無断転載を禁じます。
    特定非営利活動法人MOSA  http://www.mosa.gr.jp/
    Copyright (C)2009 MOSA. All rights reserved.

  • MOSA Developer News[MOSADeN=モサ伝]第342号

    2009-05-12

    目次

    • 「Wonderful Server Life」    第92回   田畑 英和
    • 小池邦人のCarbon視点でiPhone探求
    • ターミナルの向こうから      第47回  海上 忍 

    「Wonderful Server Life」  第92回  田畑 英和

    〜「Deployment」編〜

     前回、モデルチェンジした新しいXserveをご紹介しましたが、この新Xserve用のLOM Firmwareのアップデートがリリースされています。

    ・ニュースリリース
    http://support.apple.com/downloads/Xserve_LOM_Firmware_Update_1_2

     それでは前回の続きで「システムイメージユーティリティ」を使ったシステムイメージの作成方法について解説していきます。システムイメージを作成するにはまず、イメージのソースの準備が必要になります。

    ◇イメージのソースの準備 
     イメージのソースとは、イメージの作成元のことです。NetBoot/NetInstallではサーバ上に用意したシステムイメージをネットワークを経由してクライアントコンピュータに提供しますが、この元となる環境をまずは用意しなくてはなりません。起動可能なシステムボリュームをソースとして使用することができます。
     ソースを準備するには、まずモデルとなるMacを用意してそこでクライアントコンピュータの環境を構築します。ここで重要なのは共通のシステムイメージを複数のクライアントで共有しますので、クライアントごとに異なる内容というものは基本的にはソースの中に含めることができません。例えばクライアントコンピュータによってインストール済みのソフトウェアを変えたいといった場合1つのソースだけでは対応できないことになります。ですのでソースはあくまでもすべてのクライアントに共通の内容にしておきます。どうしても1つのソースで対応できない場合は、複数のソースから複数のイメージを作成することもできます。
     またモデルとして使用するMacの機種にも注意が必要です。基本的には実際に使用するクライアントと同じ機種を用意するのが最も問題のない方法です。もし使用するクライアントが複数の機種から構成されている場合にはその中から最新の機種を使用するようにしましょう。OSのバージョンによっては機種によって起動できたりできなかったりする場合があるからです。クライアントの機種が統一されている環境が理想的です。イメージは複数運用できますので、機種ごとにイメージを作成することも技術的には可能ですが、ただし管理の手間がかかることになります。
     ネットワーク経由でインストールを行うNetInstallの場合には、OSのインストールディスクからシステムイメージを作成することもできます。

    ◇イメージの保存場所の設定
     NetBootサービスではサーバ上でイメージを保存しておくための場所をあらかじめ用意しておく必要があります。そこで「サーバ管理」を使ってイメージの保存場所を設定します。
     「サーバ管理」でサーバに接続し、左側のリストからNetBootサービスを選択します。リストにまだNetBootが表示されていない場合は追加しておきます。
    ツールバーから「設定」をクリックし「一般」設定画面を表示します。この画面の下半分にあるのがイメージの保存場所の設定になります。ここにはサーバ上でアクセス可能なボリュームの一覧が表示されますので、イメージを保存するボリュームの「イメージ」をチェックし、「保存」ボタンをクリックします。
    すると指定したボリュームに「/Library/NetBoot/NetBootSP0」(*1)が作成されここにシステムイメージを保存することになります。イメージの保存場所として指定するボリュームには十分な空き容量があることを確認しておきましょう。

    ・イメージの保存場所の設定
    http://www.htabata.com/img/MXS105/netboot/nb_admin_01.png

     イメージの保存場所の設定の他にも「クライアントデータ」という設定項目がありますが、こちらについてはまた後ほど解説することにします。

    *1 環境によってディレクトリ名はNetBootSP1、NetBootSP2…となります

    ◇イメージの作成
     それではいよいよシステムイメージの作成です。ここではサーバ上でイメージを作成するものとします。ソースとなるモデル用のMacの準備が整ったら、ターゲットディスクモードで起動してFireWireケーブルでサーバに接続します。
    するとサーバにソースとなるシステムボリュームがマウントされます。
     次にサーバ上で「システムイメージユーティリティ」を起動し、左側のリストの「ソース」から、マウントしたシステムボリュームを選択します。
     作成するイメージのタイプを選択したら、「続ける」ボタンをクリックし、次の画面でイメージ名と説明を入力します。ここで設定したイメージ名と説明は後から「サーバ管理」で確認できますので、なにか管理しやすい情報を入力しておきましょう。
     「作成」ボタンをクリックすれば使用許諾契約が表示されますので「同意する」をクリックしてイメージの保存場所を選択します。イメージの保存場所とは先ほど「サーバ管理」で設定した「NetBootSP0」のことです。あとは「保存」ボタンをクリックするとイメージの作成が開始されます。イメージの作成にかかる時間はソースのサイズや、ハードウェアのスペックによっても異なりますが、表示メニューから「ログを表示」を選択しておけばイメージ作成の開始時刻と終了時刻を確認できますので、今後の作業の目安になるでしょう。

    ・イメージの作成
    http://www.htabata.com/img/MXS105/netboot/siu_01.png
    http://www.htabata.com/img/MXS105/netboot/siu_02.png

     それでは次回はNetBootサービスについて解説します。
                                 次回へつづく

    小池邦人のCarbon視点でiPhone探求(2009/05/08)

    〜 UIImagePickerControllerで画像取り込み 〜

    iPhone OS 3.0では画像をコピー&ペーストで別アプリケーションから持ってくることが可能になりました。しかしiPhone OS 2.2では、まだそうした操作はできません。主な画像の入手方法は、iPhoneの「写真ライブラリ」から得るか、アプリケーションから直接「写真撮影」するかのどちらかです。

    ちなみに、そうした方法以外にも、ウェブサイト上に登録されている画像を持ってきたり、MacやWindowsマシンに保存されている画像ファイルをネットワーク経由で転送したりすることも可能です。機会があれば、こうした別の方法にもチャレンジしたいと思います。また、写真ライブラリにはiTunes経由で転送された画像も含まれますが、これらの画像は、iPhoneでの表示に最適化するために、オリジナルサイズから縮小されている場合があります。また自作アプリケーションからの写真撮影では、Core Locationを利用した位置情報が画像ファイルに添付されないという制限がありますので御注意ください。

    「写真ライブラリ」からの画像の取り込みや「写真撮影」を利用するためには、UIKitに属するUIImagePickerControllerクラスを利用します。このクラスを使う場合に注意しなければいけない点は、iPod touchには「カメラ」が搭載されていないという事です。この事実を無視して、iPod touchでもカメラ撮影用の機能が使える状態になっていると(撮影ボタンなどがあると)App Storeへの登録申請において認可が下りない(リジェクトされる)ことになります。
    くれぐれも注意してください。以下は、ユーザが「画像取り込み」ボタンを押した時のターゲット&アクションの一例です。

    - (IBAction)getImage:(id)sender
    {
       NSString        *b1,*b2,*b3;
       NSString        *esc,*title;
       UIActionSheet  *action;
    
       if( [UIImagePickerController isSourceTypeAvailable:
                       UIImagePickerControllerSourceTypeCamera]==YES )
                                               //  カメラ機能が使えるかどうか?
       {
           esc=NSLocalizedString( @"ESC_BUTN",@"" );    //  キャンセル
           title=NSLocalizedString( @"ACT_TYPE_01",@"");  //  タイトル
           b1=NSLocalizedString( @"ACT_TYPE_02",@"" );  //  写真アルバム
           b2=NSLocalizedString( @"ACT_TYPE_03",@"" );  //  カメラロール
           b3=NSLocalizedString( @"ACT_TYPE_04",@"" );  //  写真撮影
           if( action=[[UIActionSheet alloc] initWithTitle:title delegate:self 
                   cancelButtonTitle:esc destructiveButtonTitle:nil 
                   otherButtonTitles:b1,b2,b3,nil] )
           {
               action.actionSheetStyle=UIBarStyleBlackTranslucent; // スタイル設定
               [action showInView:self.view];  //  方法選択のアクションシートを開く
               [action release];
           }
       }
       else
           [self actionSheet:nil clickedButtonAtIndex:0];  //  写真アルバムを開く
    }
    

    現在のデバイスでカメラが利用できるかどうかは、 UIImagePickerControllerのクラスメソッドであるisSourceTypeAvailable:で確認できます。もしカメラが使えるならば、先んじてアクションシート(UIActionSheet)を表示させ、「写真アルバム」「カメラロール」「写真撮影」の3つの方法のどれを利用するかユーザに選択させます。カメラが使用できなければ、アクションシートを表示させずに、強制的に「写真アルバム」から画像を読み込む処理を実行させます。この場合は、アクションシート上の最初のボタン(番号はゼロ)を押した処理と同等となります。

    アクションシートに表示するボタンのタイトルですが、直接ソースコード内に日本語で書き込んでも問題はありません。しかし、後々の英語ローカライズを考慮して「ja.lproj」(日本語リソース)フォルダ内に、Localizable.stringsファイルを用意し、アプリケーション内で使用する文字列をキーで参照できるよう定義しておきます。こうした文字列はNSLocalizedString()ルーチンにキーを渡して読み込むことが可能です。
    iPhoneの言語設定を変更すると読み込まれるLocalizable.stringsファイルが切り替わり、その言語設定に対応した文字列が表示される仕組みです(無ければデフォルトが使われる)。

    ESC_BUTN="キャンセル";
    ACT_TYPE_01="画像の取り込みを行えます。";
    ACT_TYPE_02="写真アルバム";
    ACT_TYPE_03="カメラロール";
    ACT_TYPE_04="写真撮影";

    さて、アクションシートが表示され、ユーザにより表示されているボタンのどれかが押されると、UIActionSheetのデリゲートが呼ばれ、そこで適切な処理へと分岐させる処理を実行させます。こうしたデリゲートのいくつかは、各クラスでプロトコルとして定義されています。今回の処理で関係するのは以下の3つのプロトコルです。

    @protocol UIActionSheetDelegate
    @protocol UIImagePickerControllerDelegate
    @protocol UINavigationControllerDelegate

    よってそれらを利用する場合には、そのクラス定義(ヘッダファイル)において、各プロトコルに準拠していることを明記しておく必要があります。この「プロトコルへの準拠」の記載がなされていないと、Make時にXcodeがアラート(警告)を表示します。以下の様に、今回のRootViewControllerクラスは3つのプロトコルに準拠していることを明記しておきます。

    @interface RootViewController : UITableViewController
    < UINavigationControllerDelegate,
    UIActionSheetDelegate,
    UIImagePickerControllerDelegate >

    アクションシートでボタンが押されると、そのデリゲートメソッドであるactionSheet: clickedButtonAtIndex:が呼ばれます。ボタン番号はbuttonIndexから得られますので、その値を確認し、キャンセルボタン以外であればUIImagePickerController(画像ピッカー)を作成して、その後の処理は全部それ(iPhone OS側)に任せてしまいます。

    - (void)actionSheet:(UIActionSheet *)actionSheet 
                                   clickedButtonAtIndex:(NSInteger)buttonIndex
    {
       UIImagePickerController    *picker;
       NSUInteger                type;
    
       if( buttonIndex!=3 )    //  キャンセルボタンではない
       {
           if( buttonIndex==0 )  //  写真アルバムから画像を読み込む
               type=UIImagePickerControllerSourceTypePhotoLibrary;
           else if( buttonIndex==1 )  //  カメラロールから像を読み込む
               type=UIImagePickerControllerSourceTypeSavedPhotosAlbum;
           else if( buttonIndex==2 )  //  写真撮影を行う
               type=UIImagePickerControllerSourceTypeCamera;
    
           if( picker=[[UIImagePickerController alloc] init] )
           {
               picker.allowsImageEditing=YES;  //  画像編集(トリミング)を許す
               picker.sourceType=type;  //  画像ピッカーのタイプを設定
               picker.delegate=self;    //  デリゲートはこのオブジェクト
               [self presentModalViewController:picker animated:YES];
                                           //  画像ピッカーをオープンする
               [picker release];
           }
       }
    }
    

    タイプ設定のための定数の名称ですが、日本語環境でのUIImagePickerController(画像ピッカー)のタイトル表示と何故だか一致していないので注意してください(仕様変更して欲しい)。
    UIImagePickerControllerSourceTypePhotoLibraryでは「写真アルバム」というタイトルが表示され、UIImagePickerControllerSourceTypeSavedPhotosAlbumの方では「カメラロール」というタイトルが表示されます。

    画像ピッカーで画像を得るための処理が正しく終了すると、以下のデリゲートメソッドが呼ばれます。引数で渡されるimage(UIImage *)が対象となる画像です。そのデータをファイルへ保存し、そのパス名をモデルオブジェクトへ登録する処理をここに記載すればOKとなります。これらの処理については、また別の機会に解説したいと思います。

    - (void)imagePickerController:(UIImagePickerController *)picker 
                           didFinishPickingImage:(UIImage *)image
                             editingInfo:(NSDictionary *)editingInfo
    {
      // ここにモデルオブジェクトへの登録と画像ファイルの保存処理を記述する
    
      [self dismissModalViewControllerAnimated:YES]; // 画像ピッカーを閉じる
    }
    
    画像ピッカーでキャンセルボタンが押された場合には、以下のデリゲートメ
    ソッドが呼ばれます。この時には何もせずに画像ピッカー
    (UIImagePickerController )を閉じます。
    
    - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker;
    {
       [self dismissModalViewControllerAnimated:YES];  //  画像ピッカーを閉じる
    }
    

    取り込んだ画像をファイルへ保存し、そのパス名をモデルオブジェクトへ登録する準備が整いました。次回からは、UIViewController(多分UITableViewController)上に配置したUITableViewにそうした画像を一覧表示させる処理へと話を進めたいと思います。

    ターミナルの向こうから      第47回  海上 忍

    〜 リモートでシェルを使う(2) 〜

    ・「scp」を知る
     scpは、Secure SHell(SSH)の機能を利用し安全にファイルコピーするためのコマンドです。UNIX系OSで古くから利用されているrcp(Remote CoPy)のSSH対応版であり、コマンドの用法はほぼ同じです。rcpと同等以上の機能を備えた、ネットワーク経由で安全なファイル転送を行うためのコマンド、と理解すればいいでしょう。scpの基本的な用法は、以下のとおりです。

    - - - - -
    scp [option] ファイル名 user@コピー先パス
    - - - - -

     ここで、通常の(単独ホスト上での)コピーを行うcpコマンドの用法と比較してみましょう。オプションを指定しないとして、第1引数が(オリジナルの)ファイル名、第2引数がコピー先(ファイルの複製をつくる先)という2点が共通していることがわかるはずです。両者の違いは、scpコマンドが「コピー先にネットワーク上のアドレスを指定できる」という点にあります。

    - - - - -
    cp [option] ファイル名 コピー先
    - - - - -

     なお、scpコマンドを利用するに際しての前提条件は、コマンド実行時に(接続先の)SSHサーバが稼働していること、SSHサーバ上にユーザアカウントが存在していること、そしてMacのターミナルなどscpコマンドを実行できる環境があることの3点です。Mac OS X Leopardを例にすると、接続先のSSHサーバ上にアカウントさえ作成済であれば、OS標準の状態で一連の機能を利用できることになります。GUIのアプリケーションを用意する必要も、事前にsshでログインしておく必要もありません。思い立ったときに最小限の装備でリモートサーバ上へファイルコピーできる点が、scpコマンドを利用するメリットです。

    ・コピー先パスを記述する

     cpとほぼ同じ用法を持つscpですが、cpはコピー先のパス(ディレクトリ)を示せば十分であることに対し、ユーザ名から始まるコピー先パスを指定しなければなりません。その記述ルールは「ユーザ名@サーバのURL:パス」で、記号「@」と「:」で区切るところがポイントです。たとえば、以下の記述例は、コピー先のサーバが「hoge.com」、サーバ上のパス(ディレクトリ)が「/public_html」、ユーザ名が「dareka」のときのものです。

    - - - - -
    dareka@hoge.com:public_html
    - - - - -

     このとき、パス(「:」以降のディレクトリ名)を省略すると、ユーザのホームディレクトリがコピー先に適用されます。

    ・手元のファイルをサーバ上にコピーする
     それでは、実例をもとにscpコマンドの使い方を紹介してみましょう。手始めに、基本形の「手元のファイルをサーバ上にコピー」することから始めてみます。コピーしたいファイルが「top.jpg」、その他の前提条件が先ほどの例と同じとすると、以下のとおり実行すればいいことになります。なお、scpコマンドは実行のつどパスワードを入力する必要があります。

    - - - - -
    $ scp top.jpg dareka@hoge.com:public_html
    dareka@hoge.com's password:
    - - - - -

    ・サーバ上のファイルを手元のMacにコピーする
     上記の例とは逆に、サーバ上のファイルを手元のMacにコピーしたい場合には、第1引数に「user@コピー先パス」を指定し、第2引数にMac上のパスを指定します。先ほどの例でサーバにコピーしたファイルを対象にする場合、次のとおりコマンドを実行することになります。

    - - - -
    $ scp dareka@hoge.com:public_html/top.jpg .
    dareka@hoge.com's password:
    - - - -

     このとき、Mac上のパスに「.」を指定すると手間がかかりません。「.」はカレントディレクトリを意味するため、その操作時点で利用しているディレクトリにファイルをコピーできるため、以下のコマンドを実行すれば、すぐにFinderでファイルを確認できます。

    - - - - -
    $ open .
    - - - - -

    ・ファイルを一括コピーする
     scpコマンドでは、cpコマンドと同様にワイルドカード「*」を使用できます(シェルにbashを利用している場合)。拡張子が同じ複数のファイルをまとめてコピーしたい場合は、以下の要領でコマンドを実行するといいでしょう。

    - - - - -
    $ scp *.jpg dareka@hoge.com:public_html
    dareka@hoge.com's password:
    - - - - -

     オプションに「-r」を指定すれば、ディレクトリ(フォルダ)ごとコピーすることもできます。たとえば、手元のMacでカレントディレクトリに存在する「MyDocs」フォルダをコピーする場合は、以下の要領でコマンドを実行します。

    - - - - -
    $ scp -r MyDocs dareka@hoge.com:public_html
    dareka@hoge.com's password:
    - - - - -

     これで、サーバ間とのファイルコピーが容易になった……といいたいところですが、ファイル1つをコピーするつどパスワードを入力するのは骨が折れる作業です。安全性を確保しつつ手間を減らすため、次回はSSHの「鍵ペア」を作成し、SSHサーバに登録する手順を紹介します。

    ◇MOSAからのお知らせと編集後記は割愛します◇

     

     MOSA Developer News   略称[MOSADeN=モサ伝]
            配信停止 mailto:mosaden-ml@mosa.gr.jp
     記事内容に関するご意見 mailto:mosaden-toukou@mosa.gr.jp
          記事投稿受付 http://www.mosa.gr.jp/?page_id=850
    Apple、Mac OSは米国アップル社の登録商標です。またそのほかの各製品名等
    はそれぞれ各社の商標ならびに登録商標です。
    このメールの再配信、および掲載された記事の無断転載を禁じます。
    特定非営利活動法人MOSA  http://www.mosa.gr.jp/
    Copyright (C)2009 MOSA. All rights reserved.