Corredor

ウェブ、プログラミングの勉強メモ。

Google Apps Script を使ってみる

Google Apps Script (GAS) は、2009年に登場した、サーバサイド JavaScript の実行基盤。今でこそ Node.js が動作する PaaS はよくあるものの、2009年当時はかなり革新的なサービスだったのではないかと推測する (当時をよく知らない)。

GAS は G Suite プラットフォームの一機能として、スプレッドシートのマクロを構築するためのモノとしても使えるし、URL を発行して簡易的な API、Webhook サーバとしても使える。さながら FaaS というか、サーバレス的な仕組みも兼ね備えている。

ユーザが記述する開発言語は JavaScript だが、それ以降にデファクトスタンダードとなった Node.js との互換性はなく、GAS 独特な書き方を求められる部分が多々ある。それらの仕様を理解するのに少し苦労しそうなので、まずは最も簡単な GAS を作ってみよう。

GAS プロジェクトを作る

まずは GAS の「プロジェクト」を作る。イマイチ新規作成するやり方が分かりづらいのだが、

のいずれかの方法で新規作成できる。

f:id:neos21:20190705211344p:plain

f:id:neos21:20190705211349p:plain

プロジェクトを作成すると、以下のような画面になると思う。ココがエディタだ。

f:id:neos21:20190705211356p:plain

「プロジェクト」と「スクリプトファイル」

プロジェクトのエディタが開いたら、最初に「コード.gs」というファイルが開かれているかと思う。

左にファイルツリーらしきペインが見えることから、1つのプロジェクトには複数のファイルが格納できることは分かるかと思う。1つのプロジェクト内には、複数の「スクリプトファイル」、すなわち .gs ファイルが作成・格納できる。

今回は紹介しないが、「ウェブアプリケーションとして導入」などで URL を発行する際、URL はプロジェクトにつき1つ発行される。スクリプトファイルは単にファイルを分けて管理できる、というだけだ。

Node.js であれば、require で別ファイルを読み込んで使えたりするが、GAS にはそのような仕組みはなく、単にグローバル変数、グローバル関数が相互に参照できるだけである。内部的には .gs ファイルを名前順に concat (結合) して実行しているだけのようだ。

HTML ファイルなどもプロジェクト配下に置けて、簡易的に Web サイトを公開したりもできるので、可能性は無限大だが、基本的には1つのプロジェクトはミニマルに、1つのスクリプトファイルで把握できるような小規模なモノを作った方が良いだろう。

お試し実装してみる

さて、コード.gs というファイルが最初から用意されているので、この中の myFunction 内に、お試しで実装してみよう。

今回は、GAS が提供しているオリジナルの関数 Logger.log() を使って、console.log() 的なコンソール出力を実現してみる。

function myFunction() {
  Logger.log('Hello World');
}

コレだけ。

f:id:neos21:20190705211400p:plain

実装したら、上のツールバーから「実行」ボタンを押してみる。画面上は特に変化がないので、「表示」メニュー → 「ログ」を選択する。

f:id:neos21:20190705211406p:plain

すると、今実行した内容が確認できる「ログ」ダイアログが表示されるはずだ。

f:id:neos21:20190705211410p:plain

どうやらサーバサイド (Google のサーバ) で JavaScript コードが実行された、ということが分かるであろう。

今日はココまで

今日はとても簡単な例だったがココまで。

GAS は歴史が長く、独特な記法・API も多いが、同時にノウハウも沢山溜まっているので、ぜひとも色々な使い方をしてみて欲しい。

詳解! GoogleAppsScript完全入門 ~GoogleApps & G Suiteの最新プログラミングガイド~

詳解! GoogleAppsScript完全入門 ~GoogleApps & G Suiteの最新プログラミングガイド~

Homebrew でインストールしたツールを実行したら「Insecure world writable dir」とかいうエラーが出た件の対処法

MacOS Mojave にて、Homebrew でインストールした ghi というツールを実行したところ、以下のようなエラーが出た。

/usr/local/Cellar/ghi/1.2.0_4/libexec/bin/ghi:128: warning: Insecure world writable dir /usr in PATH, mode 040777

ワーニングメッセージが出るだけで、その後は正常にツールが動作する。実害はないが気になる。

なんだろうこれー突然出るようになったなー、と思ったが、少し前に何かのノリで、/usr/local/ ディレクトリのパーミッションを 777 にしたのが悪かった様子。

要するに/usr/ ディレクトリ配下に書き込み権限があるのは安全じゃないですよ」という警告だったので、次のように書き込み権限だけを外してあげることで、ワーニングメッセージが出なくなった。

$ sudo chmod go-w /usr/
$ sudo chmod go-w /usr/local/

ProxyCommand を使って踏み台サーバ経由で SSH 接続するのをコマンド1発にする

「手元の PC → 踏み台サーバ → 目的のサーバ」と通信を経由して SSH 接続したい。

以前、nc コマンドを「踏み台サーバ」にインストールしておき、~/.ssh/config ファイルを書くことで、コマンド1発で SSH 接続する方法を紹介した。

neos21.hatenablog.com

今回は、nc コマンドを踏み台サーバにインストールすることなく多段 SSH する方法を紹介する。

~/.ssh/config で設定する方法

先に、~/.ssh/config に接続先情報を記述する方式から紹介する。

Host target
  HostName      target-host
  User          target_user
  Port          22
  IdentityFile  ~/.ssh/id_rsa
  ProxyCommand  ssh -W %h:%p -i ~/.ssh/id_rsa -p 22 bastion_user@129.000.0.00

HostNameUserPortIdentityFile の4つの情報は、「目的のサーバ」に接続するための情報だ。

ProxyCommand に書かれている ssh -W %h:%p はお決まりのモノとして、-i-pユーザ名@ホスト名 の情報で、「踏み台サーバ」への接続情報を指定している。

コマンド1発で書いてみる

~/.ssh/config に接続先情報を書かず、コマンドラインで実現するなら次のとおり。

$ ssh -o ProxyCommand='ssh -W %h:%p -i ~/.ssh/id_rsa -p 22 bastion_user@129.000.0.00' -i ~/.ssh/id_rsa -p 22 target_user@target-host

MacOS で Bad stdio forwarding specification '%h:%p' というエラーが発生する

自分がこのやり方に中々到達できなかったのは、ssh -o ProxyCommand='' コマンドを使った時に、

Bad stdio forwarding specification '%h:%p'

というエラーが発生して、動作しなかったためだ。

~/.ssh/config に設定を書いて実行すると上手く動いたので、何が原因なんだろうーと色々探していたのだが、原因は以前インストールした sshrc のせいだった。

neos21.hatenablog.com

自分は ~/.bashrc で、

alias ssh='sshrc'

というエイリアスを設定していたのだが、コレがどうも良くなかったみたいで、このエイリアスを削除してやると、コマンド一発でも上手く動くようになってくれた。brew install openssh とかなんとかやってグニグニしてたけど関係なかった。

Infrastructure as Code ―クラウドにおけるサーバ管理の原則とプラクティス

Infrastructure as Code ―クラウドにおけるサーバ管理の原則とプラクティス

踏み台サーバ経由で SSH ポートフォワーディングする手順

  • 手元のパソコンから
  • パブリック IP を持っている踏み台サーバを経由して
  • プライベート IP しか持たない目的のサーバ

アクセスしたい。

そして、「手元の PC ⇔ 踏み台サーバ ⇔ 目的のサーバ」という経路でポートフォワーディングして、「目的のサーバ」が 8080 ポートで公開している Web サーバを、「手元の PC」の 18080 ポートで受け取って閲覧してみる。

まずは経路確認

まずは、各サーバに入れることを確認する。

# 手元の PC から踏み台サーバに SSH 接続する
$ ssh -i ~/.ssh/id_rsa -p 22 bastion_user@129.000.0.00

## 踏み台サーバに接続できた

## 踏み台サーバから目的のサーバに SSH 接続する
$$ ssh -i ~/.ssh/id_rsa -p 22 target_user@target-host

### 目的のサーバに接続できた。目的のサーバの 8080 ポートには Web サーバが立っているテイ
$$$ curl http://localhost:8080/
Hello World, This server is TARGET-HOST.

ココが上手くいかない場合は、クラウド側のファイアウォール設定で22番ポートを封じている可能性がある。

このやり方の場合、「踏み台サーバ」から「目的のサーバ」に接続する際の鍵ファイル (~/.ssh/id_rsa) は、「踏み台サーバ」内に置いておく必要がある。

SSH 接続をポートフォワーディングしてみる

続いて、SSH 接続をポートフォワードしてみる。

# 手元の PC から踏み台サーバに接続し、「踏み台サーバから目的のサーバ」への接続経路を、ローカルの 10022 ポートに転送する
$ ssh -i ~/.ssh/id_rsa -p 22 bastion_user@129.000.0.00 -L 10022:target-host:22

このコマンドを実行すると、踏み台サーバに SSH ログインした状態になるので、このターミナルタブはそのままにして、別のターミナルタブで、次のようにアクセスする。

$ ssh -i ~/.ssh/id_rsa -p 10022 target_user@localhost

このようにすると、「手元の PC の 10022 ポート」を指定しているが、ポートフォワード設定によって「目的のサーバ」に SSH ログインできる。

この際、「目的のサーバ」に接続するために使っている鍵ファイルは、「手元の PC」にある ~/.ssh/id_rsa になるので、「踏み台サーバ」には秘密鍵ファイルを置いておく必要がなくなる。

このポートフォワード設定を ~/.ssh/config に書く

以上の2つのコマンドを ~/.ssh/config に起こしてみると、以下のようになる。

Host forward1
  HostName      129.000.0.00
  User          bastion_user
  Port          22
  IdentityFile  ~/.ssh/id_rsa
  LocalForward  10022 target-host:22

Host forward2
  HostName      localhost
  User          target_user
  Port          10022
  IdentityFile  ~/.ssh/id_rsa

ファイルを設定したら、$ ssh -fN forward1 を実行したあと、別タブで $ ssh forward2 と実行すると、目的のサーバに接続できる。

どこに「踏み台サーバ (bastion)」の情報を書くか、「目的のサーバ (target)」の情報を書くか、どこでフォワードするポート番号を指定するのかを整理して理解しておこう。

「目的のサーバ」の Web サーバのポートをローカルにポートフォワードする

ココまででポートフォワーディングのやり方が分かったと思うので、「目的のサーバ」が 8080 ポートで公開している Web サーバを、「手元の PC」の 18080 ポートで受け取って閲覧してみる。

$ ssh -i ~/.ssh/id_rsa -p 22 bastion_user@129.000.0.00 -L 18080:target-host:8080

このように叩くと踏み台サーバにログインした状態になるので、このターミナルタブはこのままに、ブラウザで次の URL にアクセスする。

  • http://localhost:18080/

ローカルの 18080 ポートにアクセスすると、踏み台サーバを経由して、「目的のサーバ」の 8080 ポートの内容が閲覧できる。最初に書いた例で行くと「Hello World, This server is TARGET-HOST.」なんていうメッセージが見えている、というワケだ。

# curl で見てみても良い
$ curl http://localhost:18080/
Hello World, This server is TARGET-HOST.

ポートフォワードをコマンド1発でバックグラウンド実行する

先程のやり方だと、踏み台サーバにログインした状態のターミナルタブが残ってしまう。コレではタブが邪魔臭いので、コマンド1発で実行したら、バックグラウンド実行してくれるようにしてみる。

$ ssh -i ~/.ssh/id_rsa -p 22 bastion_user@129.000.0.00 -L 18080:target-host:8080 -N -f -o ServerAliveInterval=60

前半の -i-p・踏み台サーバ情報、-L オプションによるポートフォワード指定までは全く同じ。違いは -N 以降のオプション群だ。

コレを指定して実行すると、SSH 接続後にプロンプトが元に戻り、SSH 接続のプロセスがバックグランド実行される。MacOS の場合は「ターミナル.app」自体を終了させても、http://localhost:18080/ にアクセスできる。

裏側ではずっとポートフォワードした状態になるので、ポートフォワードを終了する場合は、$ ps x | grep ssh でプロセス ID を調べ、kill してやる。


以上だ。

本気で学ぶ Linux実践入門 サーバ運用のための業務レベル管理術

本気で学ぶ Linux実践入門 サーバ運用のための業務レベル管理術