Corredor

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

Bash でアスタリスクを展開させないようにする

Bash のコマンド中に、アスタリスク * を「文字列」として認識させたい場合があったりする。

# 以下のような場合は「アスタリスク展開」をさせたいが…
$ cp ./* ../../dest/

# 以下のコマンドでは「アスタリスク」を文字として使いたい
$ set_char *

(set_char というコマンドは存在しないが、こういう用途があったとして…という例)

アスタリスクを展開させることを、ワイルドカード展開とか、Asterisk Expansion とか呼んだりするが、コレを無効化する方法。

シングルクォートで囲む

手っ取り早いのは、引数をシングルクォートで囲むこと。

$ set_char '*'

バックスラッシュでエスケープする

次に、バックスラッシュ文字を付与してエスケープしてやる方法。

$ set_char \*

set -fset -o noglob を指定する

set -f か、set -o noglob を実行してからコマンドを書けば、ワイルドカード展開が無効になる。

$ set -f
# もしくは
$ set -o noglob

# ワイルドカード展開されずに実行できる
$ set_char *

# 元に戻すには以下のいずれか
$ set +f
$ set +o noglob

覚えた。

[改訂第3版]Linuxコマンドポケットリファレンス

[改訂第3版]Linuxコマンドポケットリファレンス

  • 作者:沓名 亮典
  • 出版社/メーカー: 技術評論社
  • 発売日: 2015/06/05
  • メディア: 単行本(ソフトカバー)

「一度しか見られないページ」を公開するサーバを作ってみる

Cicada 3301 というミームをご存知だろうか。Twitter 上に投稿された暗号パズルなのだが、その中で「最初に正解に辿り着いた人しか閲覧できないウェブページ」という内容が出てきた。

最初に正解に辿り着いた人しか閲覧できないウェブページ…

一人しか閲覧できないページ…

一度しか見られないページ…

なんとも面白そうだ。

ということで作ってみた。

先に成果物

一度しか見られないページを実現する、Node.js 製のプログラムを書いてみた。ソースコードは以下。

github.com

$ npm start でサーバ起動後、http://localhost:8080/secret にアクセスすると、初回だけは「秘密のメッセージ」が見えるが、F5 更新などして再度アクセスすると、もうそのメッセージが見られなくなる、という作りになっている。

もう一度試してみたい場合は、$ npm run reset を実行すると、秘密のメッセージを書き込んだ secret.txt を生成し直すので、再度「秘密のメッセージ」が1回だけ見られるようになる。

仕組み

このサーバは、次のような仕組みで動いている。

  1. 予め、秘密のメッセージを書き込んだ secret.txt を用意しておく
  2. サーバ起動後、秘密のページへの初回アクセスがあったら secret.txt の中身を取得し、secret.txt を削除してからレスポンスする → 秘密のメッセージが閲覧できる
  3. 以降、秘密のページへのアクセスがあっても、secret.txt が存在しないため、秘密のメッセージが閲覧できない

$ npm run reset コマンドの処理内容は、この手順 1. にあたる。

特定のページ (このプログラムでは /secret というパス) へのアクセスがあったら、fs.readFileSync()secret.txt を取得して、その中身をレスポンスし、fs.unlinkSync() でファイルを削除している。コレにより、そのサーバ内に不正侵入できたとしても、「秘密のメッセージ」の内容は二度と見られなくなる、という寸法だ。

なお、当初は、「秘密のページにアクセスがあったかどうか」をチェックするフラグファイルでも生成して管理しようかと考えていた。

  1. 秘密のページへのアクセス時、フラグファイルの存在チェックを行う
  2. フラグファイルが存在しなければ初回アクセスとみなし、フラグファイルを生成した上でレスポンスする → 秘密のメッセージが閲覧できる
  3. フラグファイルが存在すれば2度目以降のアクセスとみなし、秘密のメッセージをレスポンスしない

このやり方だと、サーバ上に秘密のメッセージの情報が残り続けることになるので、よりセキュア (?) にしようと思って、秘密のメッセージが書かれたファイルを削除する、という仕組みにしてみた。

以上

…作ったは良いけど、コレ、何かに使えるかな……。

Webサーバを作りながら学ぶ 基礎からのWebアプリケーション開発入門 (Software Design plus)

Webサーバを作りながら学ぶ 基礎からのWebアプリケーション開発入門 (Software Design plus)

  • 作者:前橋 和弥
  • 出版社/メーカー: 技術評論社
  • 発売日: 2016/06/07
  • メディア: 大型本

Node.js で電卓 CLI アプリを作った : @neos21/calc-cli

CLI で電卓を使いたくて、Node.js でサクッと作ってみた。その名も @neos21/calc-cli : node-calc-cli

$ npm install -g @neos21/calc-cli

# 「calc」コマンドが使えるようになる
$ calc '80.7 - 10.1'
# --> 70.6

# エイリアスとして「ncalc」コマンドも用意
$ ncalc '80.7 - 10.1'

Mac 環境だと calc コマンドで動作するが、Windows だと calc.exe とバッティングするので、ncalc というコマンドも用意した。

内部的には、引数を束ねて、雑に全角文字を半角に変換してあげて、mathjs パッケージにブチ込んでやった。


元々、Bash 環境なら expr コマンドや bc コマンドなどでも簡単な計算はできるが、小数の計算とかがちゃんとやりたかったので作った次第。

neos21.hatenablog.com

neos21.hatenablog.com

mathjs を使ったことで浮動小数点の誤差は出なくなったが、Node.js ベースということもあり実行速度が微妙。Python とかで同等の CLI アプリ作り直してみようかな。

GAS を使って Slack コマンドが受け取った文字列を別のサーバに POST 送信する

Google Apps Script (GAS) で POST 送信する方法。

以前、Twitter API をコールする GAS スクリプトを書いたが、今度は Twitter のようなサードパーティライブラリが用意されていないサーバに対して、ローレベルに POST 送信をしてみる。

neos21.hatenablog.com

早速だが、実装は次のようになる。組み込み関数の UrlFetchApp.fetch() を使う。

/** Slack Verification Token */
const slackVerificationToken = '【Slack App のトークン文字列】';

/**
 * Slack からの Slash Command を受け取る
 * 
 * @param {*} event イベント
 * @return {*} JSON レスポンス
 */
function doPost(event) {
  // Slack トークンチェック
  const verificationToken = event.parameter.token;
  if(verificationToken !== slackVerificationToken) {
    throw new Error('Invalid Token');
  }
  
  // Slash Command のメッセージ部分を取得する
  const text = event.parameter.text;
  
  // POST 送信する内容を組み立てる
  const payload = {
    slackText: text
  };
  
  // POST 送信する
  const response = UrlFetchApp.fetch('http://example.com/submit.php', {
    method : 'post',
    payload: payload
  });
  
  // レスポンスの JSON をパースする (resultMessage プロパティがあるテイ)
  const responseJsonData = JSON.parse(response.getContentText('UTF-8'));
  
  // Slack へ応答メッセージを返す
  return ContentService
    .createTextOutput(JSON.stringify({
      text: responseJsonData.resultMessage
    }))
    .setMimeType(ContentService.MimeType.JSON);
}

レスポンスのテキストを取得したければ、UrlFetchApp.fetch().getContentText() で取得する。エンコーディングを第1引数で指定しておくと良いだろう。また、そもそもレスポンスが不要な場合は、変数 response で結果を受け取らなくて良い。

よくある Ajax 系のライブラリと違って、同期的に動作するのが特徴。fetchAll() という別のメソッドは非同期処理されるようだ。

上の例は Slack コマンド向けの実装になっている。Slack コマンドを通じて投げられたテキストを取得したり、呼び出し元が正しいかトークンチェックしたりしている。

仕事で使える!Google Apps 入門全集 (仕事で使える!シリーズ(NextPublishing))

仕事で使える!Google Apps 入門全集 (仕事で使える!シリーズ(NextPublishing))

  • 作者:
  • 出版社/メーカー: インプレスR&D
  • 発売日: 2015/11/20
  • メディア: Kindle版