AirPods(1)Apple Storeで当日にAirPodsを購入する方法

Apple Storeアプリで購入し店舗で受け取る

12/14に突如発売がアナウンスされたAirPods。当初は最短で12/19お届けだった配送スケジュールも、予約が殺到した結果、あっという間に伸びていき、今や6週間待ち。では、2月中旬まで待てない人は、どうやって入手したら良いのか。一番手っ取り早いのは、Apple Storeまで出向き直接購入する方法だが、これも下の写真のとおり、開店前から長蛇の列で、おまけに入荷されない日の方が多いとのこと。実際にApple Storeに開店前から並んでみたが、開店30分前には、修理や他のApple製品購入の人間も含めて、50人近くが列に並ぶという状況で、列に並んでいる途中にApple Storeの店員から、「在庫が少ないので販売は確約できない」と言われてしまう始末。ではどうしたらよいのか。

Apple Store 心斎橋

列に並んでいる人に対して、開店前にApple Storeの店員からアナウンスがあり、一番早くAirPodsを入手するためには、iOSのApple StoreアプリからAirPodsを購入して、店頭受け取りを指定するという方法が良いとのこと。実際にApple StoreアプリからAirPodsを選択してみると、

Apple Store アプリ

まさかの当日店舗受け取りが可能となっている。Apple Storeアプリからすぐさま購入すると、クレジット決済や在庫の確認等のため、15分程度処理中のステータスとなるが、その後すぐに受け取り待ちのステータスとなり、

Apple Store アプリ

受け取り待ちのステータスになったことを確認した直後に、店舗で購入を申し出ると、すぐに購入手続きへと移ることが可能でした。Apple Storeアプリの店舗受け取りにしている商品の案内は、(AirPodsに限らず)最優先で手続きしてくれるとのこと。というわけで、年内にAirPodsを購入するための最善の方法は、Apple Storeアプリで購入し店舗で受け取る。これだと寒空の下で列に並ぶ必要が無く、購入完了後の好きな時間に店舗に赴けばよい。ただし、店舗に商品が入荷されたタイミングで、当日店舗受け取りが可能なステータスに変更となるようなので、いつ購入しても当日に受け取れるというものでは無いようである。また、店舗受け取りに指定した場合は、3週間以内であればいつ来店しても確実に商品が受け取れる一方で、3週間以内という期限が設けられているので、期限切れには注意が必要だ。

AWS Identity and Access Management(1)IAMの概要

AWS Identity and Access Management (IAM)とは

AWS IAMは、AWSをセキュアに使用するための認証認可の仕組み。UserやGroupを作成してパーミッションを付与することができる。AccessKey, SecretKeyの取り扱いは注意が必要で定期的な更新が望ましい。また、Rootアカウント(アカウントを作成したときのID)はIAMの設定するポリシーが適用されない強力なアカウントになるので極力使用しない。

IAMで作成したユーザでマネージメントコンソールにログインすることが可能で、ログインURLはIAM Dashboardより確認編集することが可能である。

安全なアカウント管理のために

安全にアカウントを管理するためには以下のような手法を講じることが望ましい。

  • ルートアカウントのアクセスキーを消去する
  • ルートアカウントをMFA認証にする
  • AWSが定期着したポリシーを利用する
  • ユーザにグループを割り当て、グループごとにポリシーを定義する
  • 最小限の権限のみを与える
  • EC2で動作するアプリケーションへは、アクセスキーではなくロールで権限を与える

セキュリティ監査

セキュリティ監査を実施することで高いセキュリティレベルを維持することができる。セキュリティ監査は、定期的もしくはユーザの増減があった際や、サービスの開始/停止時、不正アクセスが疑われる際などに推測を交えずに徹底的に行うと良い。

管理ポリシー

AWSアクセスへの管理権限をJSON形式で指定することが可能である。条件(Condition)は、項目を連ねた場合はAND、項目内で条件を連ねた場合はORとして扱われる。全てのアクセスはデフォルトで拒否、Allowが指定されれば許可、Denyが指定されれば明示的な拒否として扱われる。

分類 項目例 内容
Effect Allow or Deny 許可設定であればAllow, 拒否設定であればDeny
Action s3:createBucket 操作の指定、ワイルドカードも使用可能
Resource arn:aws:s3:::mybucket service:region:account:resouceの順で記述する
Condition “IPAddress”: {“AWS:SourceIP”: “192.168.0.1”} 条件を指定する

IAMロール

AWSサービスに対してAWSアクセスの管理権限を付与する仕組み。UserやGroupには紐付かない。例えばEC2からDynamoDBやS3にアクセスする場合は、EC2上にCredentialを置くのではなくインスタンス作成時に適切なIAMロールを紐付ける。EC2へのIAMロールの紐付けは、インスタンス作成時のみ可能であることに注意が必要である。

AWSCredentialsProvider

AWSの各サービスにアクセスするプログラムをEC2上で動作させる場合に、認証情報をCredentialsから取得するのか、IAMロールから取得するのか選択することができる。Credentialsから取得する場合はProfileCredentialsProviderを、IAMロールから取得する場合はInstanceProfileCredentialsProviderクラスを使用する。

// Credentialsから取得する場合
AWSCredentialsProvider credentialsProvider = new ProfileCredentialsProvider();

// IAMロールから取得する場合
//
// 引数(refreshCredentialsAsync)をtrueにすると認証情報を非同期に更新する新しいスレッドが生成される
// falseにすると認証情報の更新は、インスタンスメタサービスに合わせられる
AWSCredentialsProvider credentialsProvider = new InstanceProfileCredentialsProvider(true);

// 認証情報の取得
credentialsProvider.getCredentials();

STS(AWS Security Token Service)

AWSには、STS(AWS Security Token Service) と呼ばれる一時的に認証情報を付与するサービスが存在し、動的にIAMユーザを作成することができる。IAM Role for EC2はこの仕組みを利用している。有効期限は数分から数時間に設定可能である。

AWS VPC (1)Amazon Virtual Private Cloud とは

VPC

各アベイラビリティゾーンのデフォルトサブネットを持つデフォルトVPCが標準で作成され、インスタンス起動時にサブネットを指定しなかった場合は、このデフォルトVPCが指定される。これに加えて、ユーザ独自にデフォルト外VPCを作成することが可能である。VPCは、ルータを通じて他のVPCと接続(ピアリング接続)したり、S3などの他のAWSサービスのエンドポイントと接続したり、VPN経由で自社のネットワークと接続したりすることが可能である。VPCを利用するAWSサービスの例としては、AWS Data Pipeline, Elastic Beanstalk, Elastic Load Balancing, Amazon ElastiCache, Amazon EMR, AWS OpsWorks, Amazon RDS, Amazon Redshift, Route 53などがある。

VPCは生成する際にサイズを指定することが可能で、/16から/28までを指定できる。生成後にサイズを変更することはできないが、セカンダリ IPv4 CIDR ブロックを関連付けることができる。指定するCIDR ブロックは、プライベートIPアドレスの範囲から指定することが望ましい。

デフォルトVPC

デフォルトVPCには、ルータインターネットゲートウェイが含まれており、各サブネットは、インスタンスに対してパブリックIPの割り当てが実行される、インターネットに接続可能なパブリックサブネットである。サブネットを指定せずにEC2を起動した場合は、デフォルトVPCで起動される。デフォルトVPCでは、サイズ /16 の IPv4 CIDR ブロック (172.31.0.0/16) の作成と、インターネットゲートウェイとの接続を行う。新しいアベイラビリティーゾーンが追加された場合は、数日以内に、このアベイラビリティーゾーン内でデフォルト VPC の新しいデフォルトサブネットが自動的に作成される

デフォルトVPC

デフォルト外VPC

デフォルト外VPCには、ルータやインターネットゲートウェイが含まれておらず、自分で設定に加える必要がある。また、サブネットも標準では、パブリックIPの割り当てが行われず、プライベートサブネットに設定されている。

デフォルト外VPCでインターネット接続を可能にするためには、インターネットゲートウェイのアタッチや、ルーティングテーブルの追加、各インスタンスへのElastic IPの割り当てが必要である。プライベートサブネットの場合、サブネット内のインスタンスが直接インターネットに接続することができないため、別のパブリックサブネット内にNAT gatewayを生成し、このNAT gateway経由でインターネットと接続を行う。Elastic IPの数には限りがあるので、静的なIPアドレスを多く使用するようなネットワーク構成の場合にも、NAT gatewayは有効である。なお、NAT gatewayはIPv6には非対応である。

サブネット

サブネットは、アベイラビリティゾーン単位で指定できる。サブネットは生成する際にサイズを指定することが可能で、/16から/28までを指定できる。指定したCIDR ブロックの先頭4アドレスと最後の1アドレスは使用することができない。なお、先頭アドレスは、ルータに接続されるIPアドレスとなっている。また、CIDRブロックのサイズを後から増減することはできない

インターネットに接続する必要のあるリーソースの場合は、パブリックサブネットを、インターネットに接続しないリソースの場合は、プライベートサブネットに接続する。

サブネット

ルーティング

各VPCには暗黙的なルータ(implied router)が存在し、標準ではVPC内の各サブネット間の通信のみ許可されている。また、ルートテーブルは、標準で生成されるメインルートテーブルと、各サブネットにそれぞれ割り当てることが可能なカスタムルートテーブルが存在する。明示的にルートテーブルの関連付けを行わない場合は、メインルートテーブルにアタッチされる。インターネットゲートウェイを通じて、インターネットに接続する場合は、ルートテーブルにインターネットゲートウェイへの経路を明示的に追加する必要がある。また、VPN、Direct Connect、VPC Peeringでは、2hop以上先のネットワークとは通信できない

インターネットゲートウェイ(IGW)

EC2へインターネットへの接続を提供する。サブネット単位でルーティングを指定でき、インターネットゲートウェイを指定したサブネットをパブリックサブネットと呼ぶ。インターネットとの間で通信が必要なインスタンスには、パブリックIPの付与が必要となる。冗長性と高い可用性を有しており、水平スケーリングが可能である。

バーチャルプライベートゲートウェイ(VGW)

VPN接続やDirect Connect接続のエンドポイントを提供する。1つのVPCあたり1つのVGWを接続することができる。

カスタマーゲートウェイ(CGW)

オンプレミス側のVPNエンドポイント。

NATゲートウェイ

NATゲートウェイには、1つElastic IPを付与することができ、プライベートサブネットのインスタンスからインターネットへの接続を可能とする。インターネット側からのサブネットへのアクセスは許可されない。NATゲートウェイは、パブリックサブネットに配置する必要がある。また、NATゲートウェイは、5Gbpsの帯域をサポートし、最大45bpsまで自動的に拡張される。タイムアウト時、NAT GatewayはRSTパケットを送信するが、NATインスタンスの場合はFINパケットを送信する。

VPCピアリング

異なるVPC間でルーティングを行うサービス。MTUは1500
同一リージョン内のVPCのみ接続可能で、重複したCIDRブロックのサブネットは接続できない

ネットワークインタフェース

ネットワークインタフェースは、インスタンスにアタッチ、デタッチしても属性情報は変わらない。1つのインスタンスに複数のネットワークインタフェースをアタッチすることで、管理用ネットワークを別に作成することなどが可能となる。一方で、複数のネットワークインタフェースが存在すると、パブリックIPアドレスの自動割り当ては利用不可となる。

プライマリプライベートIPアドレスは、一度設定すると変更することはできない。セカンダリプライベートIPアドレスは、異なるインタフェースに割り当て直すことが可能である。EC2インスタンスは、プライベートIPアドレスのみを認識し、割り当てられたパブリックIPアドレスは、インターネットゲートウェイでNATされる。パブリックIPアドレスを有効化している場合、Elastic IPを指定しない限りアドレスは、起動時に自動的に割り当てられる

パブリックIP

ネットワーク帯域

同一リージョン内通信の場合、最大25Gbpsが利用可能となる。

通信方式 同一プレイスメントグループ 同一リージョン S3 リージョン外
シングルフロー 最大10Gbps 最大5Gbps 最大25Gbps 最大5Gbps
マルチフロー 最大25Gbps 最大25Gbps 最大25Gbps 最大5Gbps

セキュリティ

ネットワークアクセスリスト(NACL)

サブネットごとに設定するフィルタ。ステートレス。デフォルトは全て許可

セキュリティグループ

EC2の仮想インタフェースとして機能。ステートフル。デフォルトは全ての通信を禁止。拒否ルールは記述できない。また、デフォルトのセキュリティグループは削除できない

VPCのセキュリティ

DNS

各VPCにはDNSが用意されており、VPCのネットワーク範囲(CIDR)のアドレスに+2したIPで参照が可能。参照が可能なのはVPC内のEC2のみで、Direct Connect等で接続したオンプレミス環境からは参照することができない

フローログ

VPC のネットワークインターフェイスとの間で行き来する IP トラフィックに関する情報をキャプチャできるようにする機能。データは、CloudWatch Logs と Amazon S3 に出力することができる。

VPCエンドポイント

VPCエンドポイントを用いることで、AWSサービスやVPCエンドポイントサービスをプライベートに接続することができる。VPCエンドポイントを用いることでインターネットに出ることなく各種AWSサービスと通信を行うことができる。冗長性と高可用性を持ち、帯域幅の制約は存在しない。対応しているAWSのサービスは以下の通り。

インタフェースエンドポイント

プライベートIPアドレスを持つエンドポイント。プライベート DNSオプションを有効化しておくことで、通常のエンドポイントが、プライベートIPアドレスに置換される。

  • Amazon API Gateway
  • Amazon CloudWatch
  • Amazon CloudWatch Events
  • Amazon CloudWatch Logs
  • AWS CodeBuild
  • Amazon EC2 API
  • Elastic Load Balancing API
  • AWS Key Management Service
  • Amazon Kinesis Data Streams
  • Amazon SageMaker ランタイム
  • AWS Secrets Manager
  • AWS Service Catalog
  • Amazon SNS
  • AWS Systems Manager

ゲートウェイエンドポイント

ゲートウェイエンドポイント

ルートテーブルに指定されたルートのターゲットとなるエンドポイント。VPC ルートテーブルを指定する必要がある。

  • Amazon S3
  • DynamoDB

インタフェースエンドポイント

Google Play Developer ConsoleでOpenSSLのバージョンエラーが発生したときの対応法

Cocos2d-xを使ったアプリをGoogle Playで公開しようとするときに、以下のエラーが表示されてAPKの公開を拒否される場合がある。

更新が拒否されたアプリ

このAPKは、セキュリティの脆弱性が含まれている点が悪意のある行為に関するポリシーに違反しているため、非承認となりました。

発生した問題

アプリで使用中のOpenSSLのバージョンにセキュリティの脆弱性があります。

Cocos2d-xには、OpenSSLのライブラリが含まれているため、OpenSSLの機能を使っていない場合でも、含まれているOpenSSLのバージョンによっては上記の警告が出る場合がある。その際は、下のリンクにもあるように、内含されているOpenSSLのバージョンを上げる必要がある。

XCodeからiTunes Connectへアップロード後に`has change to Invalid Binary`エラー

XCodeからiTunes Connectへアーカイブファイルをアップロードした後にhas change to Invalid Binaryエラーが発生した場合は、問題の詳細がメールで送信されてくる。

Missing Push Notification Entitlement

Missing Push Notification Entitlementは、Apple Developer > Certificates, Identifiers & Profiles > App IDsでPush Notificationsが有効化されていないか、もしくは、XCode -> TARGET -> Capability -> Push NotificationsでPush Notificationsが有効化されていないかのいずれかの場合が多いため、これらの設定を見直した上で再度アップロードを行う。

Missing Push Notification Entitlement – Your app includes an API for Apple’s Push Notification service, but the aps-environment entitlement is missing from the app’s signature. To resolve this, make sure your App ID is enabled for push notification in the Provisioning Portal. Then, sign your app with a distribution provisioning profile that includes the aps-environment entitlement. This will create the correct signature, and you can resubmit your app. See “Provisioning and Development” in the Local and Push Notification Programming Guide for more information. If your app does not use the Apple Push Notification service, no action is required. You may remove the API from future submissions to stop this warning. If you use a third-party framework, you may need to contact the developer for information on removing the API.

Certificatesの修正が必要な場合

Push Notificationsを有効化

XCode上で修正が必要な場合

Push Notificationsを有効化

privacy-sensitive data without a usage description

iOS10よりユーザデータにアクセスする場合は、使用目的をInfo.plistに記述する必要がある。

We have discovered one or more issues with your recent delivery for “YOUR APP NAME”. To process your delivery, the following issues must be corrected: This app attempts to access privacy-sensitive data without a usage description. The app’s Info.plist must contain an NSCameraUsageDescription key with a string value explaining to the user how the app uses this data.

Info.plistに記述した文言は、データアクセスの許可を求めるポップアップ上に表示される。NAVITIMEアプリの場合はこんな感じ。

NAVITIMEアプリ

Fluentd + Elastichsearch + Kibana(4)Fluentdでホスト名を追加する

Fluentdでログを転送する際、ホスト名も付加したい。そんなときは、標準のfilterプラグインを使って、以下の設定を加える。

sudo vi /etc/td-agent/td-agent.conf

<filter **>
  @type record_transformer
  <record>
    hostname ${hostname}
  </record>
</filter>

このときに、matchタグよりも上位に記述しないと動作しないので注意が必要である。

Fluentd + Elastichsearch + Kibana(3)FluentdからElasticsearchへの転送

Fluentdの設定

前回までにFluentd + Elastichsearch + Kibanaの環境設定と、ログの送信元となるMacの設定を行った。

今回は、受信したデータをElasticsearchに転送する処理を扱う。設定は以下の通り。

sudo vi /etc/td-agent/td-agent.conf

<source>
  @type forward
</source>

<match example.app>
  type elasticsearch
  host localhost
  port 9200
  type_name exampleapp
  logstash_format true
</match>

type_nameは、Elasticsearchタイプ名を指定する。識別できる文字列なら好きに指定して良いようだ。logstash_formatは、logstashフォーマットで出力するオプションで、とりあえず今回はtrueにしておく。

Fluentdの再起動

Fluentdを再起動する。

sudo systemctl restart td-agent

Kinabaにアクセス

Kibanaにアクセスすると、データの受信に伴って、インストール直後とは表示が変わっている。ログインすると受信データが確認できる。

https://XXX.XXX.XXX.XXX:5601

  • インストール直後
    Kibana
  • データ入力完了後
    Kibana

Fluentd + Elastichsearch + Kibana(2)MacでFluentdを動かそう

インストールと起動

MacにFluentdをインストールし、Macで動くアプリのログを、Elastichsearchが動くサーバへと転送する。FluentdのダウンロードページにMac用のdmgイメージがあるので、これをダウンロードし実行する。

Mac Fluentd dmg

Macのデーモンは、launchctlと呼ばれるツールで管理される。launchctlは、設定ファイル(plist)のロードによってデーモンを登録し、デーモンの開始や終了など制御する。通常は、デーモンの登録を行った上で、デーモンの開始を行うという流れとなるが、設定ファイル内で「RunAtLoad = true」が設定されている場合は、ロードと同時にデーモンが起動され、OSの起動時にも自動的にデーモンは起動する。

Fluentd(td-agent)の設定ファイルは、「RunAtLoad = true」に設定されているため、設定ファイルをロードするだけで、デーモンは起動され、自動起動に設定される。

launchctl load /Library/LaunchDaemons/td-agent.plist 

元データの設定

Fluentdは、元データの指定と転送先の指定が必要となる。元データは以下のような種類を指定できる。

ログファイルから取得する

転送ログの元データを指定する。設定するパラメータは以下の通り。

パラメータ 意味
type tail
path ログファイルのパス
pos_file 読み込んだ位置を記憶しておくファイル
tag ログの識別子
<source>
  type tail
  format apache
  path /var/log/httpd-access.log
  tag td.apache.access
</source>

httpから取得する

http通信によってデータを取得する。設定するパラメータは以下の通り。

パラメータ 意味
type http
port ポート番号

tagは、URLヘッダで指定する。

<source>
  type http
  port 8888
</source>

実行したコマンドの標準出力から取得する

コマンドの実行によってデータを取得する。設定するパラメータは以下の通り。

パラメータ 意味
type exec
command 実行するコマンド
tag ログの識別子

他のFluentdから取得する

他のFluentdから転送されたデータを受信する。設定するパラメータは以下の通り。

パラメータ 意味
type forward
<source>
  type forward
</source>

設定例

今回は、Macで動作するアプリが出力する以下の形式のログを元データに指定する。

2016-08-11 04:56:31.518 exampleApp[321:2853] <Normal> "Application is started."
2016-08-11 04:56:31.518 exampleApp[321:2853] <Normal> "Application is initialized."
2016-08-11 04:56:31.518 exampleApp[321:2853] <Normal> "Data is received: apple=3, orange=4"
2016-08-11 04:56:31.518 exampleApp[321:2853] <Normal> "Application will be terminated."

Fluentdは様々なログをJSON形式に変換した上で転送を行う。ログの変換を行うためには、どのようなフォーマットでログが記述されているかを正規表現でFluentdに教えてあげる必要があり、この設定が最も難しい。今回のログは、スペース区切りで、[日付][プロセス情報][ステータス][メッセージ]の情報が並んでいるので、正規表現で表現すると以下のようになる。

sudo vi /etc/td-agent/td-agent.conf

<source>
  type tail
  path /tmp/exampleApp.log
  pos_file /var/log/td-agent/exampleApp.log.pos
  tag example.app
  format /(?<time>[^\]]*) (?<process>.*) <(?<stat>.*)> "(?<message>.*)"/
  time_format %Y-%m-%d %H:%M:%S.%N
</source>

出力先の設定

Fluentdは、出力先も様々な方法を選択できる。

標準出力に転送

データを標準出力に転送する。設定するパラメータは以下の通り。

パラメータ 意味
type stdout
<match **>
  type stdout
</match>

ファイルに転送

データをファイルに転送する。設定するパラメータは以下の通り。

パラメータ 意味
type file
path 出力ファイルのパス
time_slice_format ファイル名のサフィックス
time_slice_wait ファイルを分割する時間単位
<match **>
  type file
  path /var/log/fluent/exampleApp.export
  time_slice_format %Y%m%d
  time_slice_wait 10m
</match>

他のFluentdに転送

データを他のFluentdに転送する。設定するパラメータは以下の通り。

パラメータ 意味
type forward
server 転送先サーバの情報

今回は、Macアプリのログを、Elasticsearchを導入した他のサーバに転送したいので、以下の設定とした。

<match **>
  type forward
  <server>
    name server_1
    host XXX.XXX.XXX.XXX
  </server>
</match>

設定ファイル

設定ファイルは以下となった。

sudo vi /etc/td-agent/td-agent.conf

<source>
  type tail
  path /tmp/exampleApp.log
  pos_file /var/log/td-agent/exampleApp.log.pos
  tag example.app
  format /(?<time>[^\]]*) (?<process>.*) <(?<stat>.*)> "(?<message>.*)"/
  time_format %Y-%m-%d %H:%M:%S.%N
</source>

<match **>
  type forward
  <server>
    name server_1
    host XXX.XXX.XXX.XXX
  </server>
</match>

Fluentdを再起動して新たな設定ファイルを読み込む。このとき、/var/log/td-agent/td-agent.logに正常なログが吐き出されていたらOK!

launchctl unload /Library/LaunchDaemons/td-agent.plist 
launchctl load /Library/LaunchDaemons/td-agent.plist 

参考になるページ

シェル(1)Bashの基本設定

Bashとは

シェルは、コマンドライン・インタプリタとも呼ばれ、ユーザが入力したコマンドをカーネルに渡すプログラムである。シェルには、Bashcshzshなど様々な種類が存在するが、LinuxやMac OSでは、Bashが標準シェルとなっている。/bin/shは、Linuxにおける標準シェルを示しており、通常はBashへのシンボリックリンクとなっている。

$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4  9月 26 15:52 2014 /bin/sh -> bash

なお、Bashを/bin/shとして実行させるとPOSIX準拠モードで起動するため、厳密にはBashと挙動が異なる。以下のコマンドを実行することで、インストール済みのシェルを確認することができる。

$ cat /etc/shells 
/bin/sh
/bin/bash
/sbin/nologin
/bin/dash
/bin/tcsh
/bin/csh

ファイルディスクリプタ

シェルは、実行するプログラムの以下の値を取得することが可能となっている。

ディスクリプタ 略記 内容
<0 < 標準入力
>1 > 標準出力
>2 >2 標準エラー出力

標準出力も標準エラー出力も同時に出力したい場合は、2>&1と記述する。

ショートカット

カーソルの移動や編集を行う際に以下のショートカットを使うと便利。

コマンド 意味 内容
Ctrl + a ahead 行頭に移動
Ctrl + e end 行末へ移動
Alt + b before 一単語左へ
Alt + f foward 一単語右へ
Ctrl + d delete カーソルの文字を消す
Ctrl + h 0x08 (Backspace) カーソルの左の文字を消す
Ctrl + w word カーソルの左の単語を消す
Ctrl + u unix-line-discard カーソルより左の文字を全てカット
Ctrl + k kut カーソルより右の文字を全てカット
Ctrl + y yank ペースト
Ctrl + p previous 前の履歴を表示
Ctrl + n next 次の履歴を表示
Ctrl + r reverse 過去の履歴から検索
OLDPWD 直前にいたディレクトリ

設定ファイルの読み込み順序

bashの設定ファイルはいくつもあるが、以下の順序で読み込まれるらしい。

読み込み順序 読み込み時 対象 ファイル
1 ログイン時 全ユーザ /etc/profile
2 ログイン時 各ユーザ ~/.bash_profile
3 ログイン時 各ユーザ ~/.bash_login
4 bash起動時 各ユーザ ~/.bashrc
5 ログイン時のシェル終了時 各ユーザ ~/.bashrc

PATHを通すときなどに無意識に~/.bashrcにPATHを書いてたけど、~/.bashrcにPATHを書いてbashを複数タブで起動すると、その度に同じPATHが追加されてしまうようだ。というわけで、設定ファイルは、~/.bash_profileに書いておけばいいということか。

設定ファイルの内容

historyコマンド時に時間情報も表示させると便利。
過去のコマンドが消えてしまわないように、historyの上限値も増やしておくと、なお便利。
ちなみに、![履歴番号]で、history内の過去のコマンドを実行できる。

# History
HISTSIZE=50000
HISTTIMEFORMAT='%Y-%m-%d %H:%M:%S '

# Path
PATH="$PATH":/usr/local/bin:/bin:/sbin:/usr/bin

コマンドの実行

シェルで実行ファイルを実行する場合、PATH付きで指定しなければいけない。カレントディレクトリの実行ファイルを、

$ ./a.out

などと書くのは上記ルールによる。ただし、シェルにPATHが通っている場合は、PARHを省略できる。実行したファイルのPATHを確認するにはwitchコマンドを使って、

$ witch ls

alias ls='ls --color=auto'
	/bin/ls

とすればよい。また、cd, echo, pwdなどのコマンドは、ビルトインコマンドと呼ばれ、シェル自身に組み込まれたコマンドである。コマンドのタイプを確認するためには、

$ type pwd
pwd is a shell builtin

typeコマンドを使用する。

AWS S3(2)S3Sync:S3バックアップツール

S3Sync

以前、S3にバケットを作成してGlacierアーカイブを行う手順を確認したが、この仕組みを利用してMacの任意のディレクトリをS3 Glacierと自動的に同期するアプリケーション「S3Sync」を作ってみた。Macのスリープを検知すると同期を始めるので、寝ている間にラクラク同期できる。

といってもこのアプリ、単にNSTaskを使ってシステムコマンドを実行しているだけのアプリなので、任意のコマンドを自由に実行することができる。ステータスバーに常駐しているアプリなので、作業の邪魔にもならない。

S3Sync

スリープ検知

スリープ検知をするには、NSWorkspace ClassNSWorkspaceWillSleepNotification属性を使う。

    func applicationDidFinishLaunching(aNotification: NSNotification) {
        // スリープ検知
        NSWorkspace.sharedWorkspace().notificationCenter.addObserver(self, selector: #selector(self.receiveSleepNotification(_:)), name: NSWorkspaceWillSleepNotification, object: nil)
    }

    func receiveSleepNotification(notification: NSNotification){
        // スリープ実行時に行う処理
    }

システムコマンドの実行

システムコマンドは、NSTask Classから実行することが可能である。
NSTaskは、実行したシステムコマンドの出力結果を取り出すことも可能だが、readDataToEndOfFile()を使うとブロッキング処理が発生してしまうので、dispatch_async()を使って非同期に順次出力処理していく必要がある。

let task = NSTask() 
// 実行コマンドをフルパスで指定
task.launchPath = "/usr/local/bin/aws "
// パラメータを配列形式で指定
task.arguments = ["-h", "hogehoge"]
// 標準出力をパイプに渡す
let pipe: NSPipe = NSPipe()
task.standardOutput = pipe
let stdoutHundle = pipe.fileHandleForReading     
// 非同期処理
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), {
var dataRead = stdoutHundle.availableData
while(dataRead.length > 0){
	let stringRead = NSString(data: dataRead, encoding: NSUTF8StringEncoding)
        if let output = stringRead {
		// 出力結果処理
        }
        dataRead = stdoutHundle.availableData
}
// コマンドの実行
task.launch()

NSTaskは、suspend()terminate()を使って、途中で処理を停止したり、完全に終了してしまったりすることができる。suspend()で中断した処理は、resume()で再開することができる。また、タスクが実行中にも関わらず再度launch()を実行してしまうと、下記の実行エラーが発生してしまう。

task already launched

通知の送信

本アプリは、コマンド実行毎にMacの通知センターに実行状況を通知する。

アプリ通知

Macの通知センターに通知を送信するには、NSUserNotificationCenter Classを使う。送信する通知には、「タイトル」「サブタイトル」の他に様々な項目を設定することが可能である。

// NSUserNotificationCenterDelegateが必要
class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDelegate {

    func deliverNotification(title : String, subtitle : String, informativeText: String){
        // AppDelegate Classにデリゲードを指定
        NSUserNotificationCenter.defaultUserNotificationCenter().delegate = self
        let notification = NSUserNotification()
        notification.title = title
        notification.subtitle = subtitle
        notification.informativeText = informativeText
        notification.contentImage =  NSImage(named: "MainIcon")
        notification.userInfo = ["title" : "タイトル"]
        NSUserNotificationCenter.defaultUserNotificationCenter().deliverNotification(notification)
    }

}

ログを保存するディレクトリの指定

本アプリは、実行ログをファイルに保存することができる。

NSOpenPanel

Macでディレクトリやファイルを開くする際は、NSOpenPanel Classを利用する。
また、保存の際はNSSavePanel Classというクラスも用意されている。

// MARK: ディレクトリ選択画面
let panel = NSOpenPanel()
// ファイル選択の可否
panel.canChooseFiles = false
// ディレクトリ選択の可否
panel.canChooseDirectories = true
// 複数選択の可否
panel.allowsMultipleSelection = false
panel.beginWithCompletionHandler({(num) -> Void in
      if num == NSModalResponseOK {
           // ディレクトリ・ファイル決定時の処理
      }
})

常駐アプリ

ステータスバーに常駐するアプリを作成するためには、Project > TARGET > Info > Custom OS X Application Target Propertiesから、Application is agent (UIElement)YESに設定する。

Application is agent

StoryBoardのTips

  • 常駐アプリであっても、Main Menu > Edit がないと、TextFieldの Shortcut Keyが使えない

Main Menu : Edit