ちら帳

喉元を過ぎると熱さを忘れる自分の為の、ちら裏メモ帳ブログです。

Qiitaのぐるぐるまわるコメントテスト会場が面白い

とにかくはっちゃけてて面白いので未読の方はぜひ一読を。

qiita.com

ぐるぐるぐるー





<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<span class="fa fa-spin" style="color:#ff7f7f"><span class="fa fa-spin" style="color:#ff7fbf"><span class="fa fa-spin" style="color:="#ff7fff""><span class="fa fa-spin" style="color:#bf7fff"><span class="fa fa-spin" style="color:#7f7fff"><span class="fa fa-spin" style="color:#7fbfff"><span class="fa fa-spin" style="color:#7fffff"><span class="fa fa-spin" style="#7fffbf"><span class="fa fa-spin" style="color:#7fff7f"><span class="fa fa-spin"style="color:#bfff7f"><span class="fa fa-spin" style="color:#ffff7f"><span class="fa fa-spin" style="color:#ffbf7f"></span></span></span></span></span></span></span></span></span></span></span></span>

2017/6/16 追記

元の記事が盛り上がりすぎて重たくなっていますね。自分のスマートフォンからはもう見れなくなってしまいました。
もしかすると元の記事を見れずにこちらの記事を見ていただいてる方もいらっしゃるかもしれないので、とりあえず概要的なものを追記しておきます。

Font Awesomeという、とても有名なWebアイコンフォントがありまして、アイコンに対して表示効果(アニメーションとか)を付与するクラスなんかも提供されてたりします。

fontawesome.io

それで今回、Font Awesomeの効果をアイコン以外に使う遊びが流行っているのです。

発端となった記事

qiita.com

入力にHTMLタグを許容するタイプの入力フォームは対応大変そうですね。

技術的には

 .markdown-form * { animation: none !important; } 

とか指定しておけばアニメーションを止められると思うのですが、要件的にそれやっていいのかどうかとか色々とあると思うので。

おわり

2017/6/20 追記

QiitaでHTML要素の属性指定ができなくなったそうです(一部の外部サービスの貼り付けを除く)

http://blog.qiita.com/post/162037299989/disable-html-class
blog.qiita.com

過去にはbootstrapの属性を利用したXSS脆弱性もあったようですし、こういうのって色々としょうがないのかなと思う今日この頃です。

ただWebフォントを使えなくなるのはちょっと残念だなと思いました。
emojiじゃなくてシンプルなアイコンフォントを好んで使っていた方もいたのではないかと思うので。 これを機にemojiが拡張されたりとか…厳しいかなあ。

React VR : 注視カーソルでクリックする

React&Three.js初心者のため、週一で記事を書くのがそろそろ厳しくなってきました。ちらです。

今回はVR界隈ではちょくちょく見かける、見つめているとクリックできるボタンを作りました。

作ったボタン

ボタンを見つめている間、何も起きないと面白くないので、次のような効果もつけました。

  • ボタンを見つめているかどうかでボタンのテキストが変わる
  • ボタンを見つめている間はボタンがぶるぶるする
  • 物理クリック or 注視クリックされたらボタンのテキストが変わってクリック音もする

結果、できたものがこちらです(GIFを撮る都合上、VRモードにはしていません) f:id:chira_pym:20170612222738g:plain

こうして見てみると、もっとまともな例を作るべきだった気がしてなりませんが、寝ている顔文字をぶるぶるさせるのも、クリック時にお布団から飛び出るようにするのも実装しているときは結構楽しかったです。

実装

カーソルの表示

注視入力を実装するにあたりカーソルを表示させる必要があります。

詳しい説明については、以前記事に書いたので割愛します。 chira-memo.hatenablog.com

注視クリックできるボタンの実装

注視でボタンをクリックできるようなAPIはないので、onEnterの発火時にsetTimeoutを使って、クリックしたときに実行したい処理を1秒後に実行するようにします。
視線がボタンから外れたり、入力機器を使ってボタンがクリックされたときにはclearTimeoutでタイマーを解除します。

今は自力で実装する必要がありますが、UI的にはよくあるパターンのひとつなので、そのうち標準APIになったりするのかもしれません。

サウンドの再生についてはこちらを参考にしました。

facebook.github.io

アニメーションは…ドキュメントを読んでもあまりよく分からなかったので、参考になりそうなコードを見つけてきて見様見真似で書きました。変な書き方になってたらごめんなさい。

そのうちアニメーションについても記事が書けるといいなと思います。

"use strict";

import React from "react";
import {
    AppRegistry,
    asset,
    Pano,
    Text,
    Image,
    View,
    VrButton,
    Animated,
    VrSoundEffects
} from "react-vr";

import CylindricalPanel from "CylindricalPanel";

const Easing = require("Easing");

class ReactVrSample extends React.Component {
    render() {
        return (
            <View>
                <Pano source={asset("chess-world.jpg")} />
                <CylindricalPanel
                    layer={{ width: 2000, height: 720 }}
                    style={{ position: "absolute" }}
                >
                    <View
                        style={{
                            opacity: 1,
                            width: 2000,
                            height: 720,
                            alignItems: "center",
                            justifyContent: "center",
                            marginTop: 100
                        }}
                    >
                        <SleepingButton />
                    </View>
                </CylindricalPanel>
            </View>
        );
    }
}

class SleepingButton extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            text: "(¦3[___]",
            shakeValue: new Animated.ValueXY({ x: 0, y: 0 })
        };

        this.clicked = this.clicked.bind(this);

        VrSoundEffects.load({
            wav: asset("click.wav"),
            ogg: asset("click.ogg"),
            mp3: asset("click.mp3")
        });
    }

    render() {
        return (
            <Animated.View
                style={{
                    transform: this.state.shakeValue.getTranslateTransform()
                }}
            >
                <VrButton
                    onEnter={() => this.enter()}
                    onExit={() => this.exit()}
                    onClick={() => this.click()}
                >
                    <Text
                        style={{
                            margin: 10,
                            width: 400,
                            fontSize: 70,
                            fontWeight: "300",
                            borderRadius: 20,
                            backgroundColor: "pink",
                            textAlign: "center"
                        }}
                    >
                        {this.state.text}
                    </Text>
                </VrButton>
            </Animated.View>
        );
    }

    enter() {
        this.timeout = window.setTimeout(this.clicked, 1000);
        this.setState({ text: "(:3[___]" });

        const shakeValue = 1;

        this.animation = Animated.parallel([
            this.shake(shakeValue, shakeValue)
        ]);

        this.animation.start();
    }

    exit() {
        this.timerReset();
        this.clearAnimation();
        this.setState({ text: "(¦3[___]" });
    }

    click() {
        this.timerReset();
        this.clicked();
    }

    clicked() {
        this.clearAnimation();
        this.setState({ text: "(:з )=[___]" });
        VrSoundEffects.play({
            wav: asset("click.wav"),
            ogg: asset("click.ogg"),
            mp3: asset("click.mp3")
        });
    }

    timerReset() {
        if (!this.timeout) {
            return;
        }

        window.clearTimeout(this.timeout);
        this.timeout = null;
    }

    clearAnimation() {
        if (!this.animation) {
            return;
        }

        this.animation.stop();
        this.animation = null;
    }

    shake(x, y) {
        return Animated.sequence([
            Animated.timing(this.state.shakeValue, {
                duration: 30,
                toValue: { x, y },
                easing: Easing.linear
            }),
            Animated.spring(this.state.shakeValue, {
                toValue: { x: 0, y: 0 },
                friction: 0.5,
                tension: 400
            })
        ]);
    }
}

AppRegistry.registerComponent("ReactVrSample", () => ReactVrSample);

ボタンじゃなくてカーソルの方をアニメーションしたい

できればカーソルをリング型にして、進捗状況が分かるようなプログレスリングにしたいところなのですが、 カーソルの描画部分はライブラリの方にハードコードされてしまっているので難しいのが現状です。

github.com

makeDefaultCursorメソッド内にこんな感じのコメントがついているのでそのうちカスタマイズできるようになるかもしれません。

// TODO: Customize color or change color on hit.
// TODO: Support image provided by us or by user.

自分はおとなしくアップデートを待ちたいと思います(´・ω・`)

今日のひとこと

JSXのインデントのつけ方が全然分からないのでJsPreitterをSublime Textに入れました。
プラグインなしでは生きていけない体になりつつあります。

React VRでVrButtonに効果音をつける

今日も今日とてひっそりとReact VRをいじっております。ちらです。

今回は画面内にボタンを置いて、フォーカスが当たる・クリックされるといったイベントが発生したら効果音を鳴らすようにしてみます。

f:id:chira_pym:20170605031426p:plain

ボタンを表示する

ボタンの表示にはVrButtonコンポーネントを使います。 HTMLの<button>にとてもよく似ていますが、VrButtonはイベントをキャプチャするためのラッパーであり、外観を持たないようです。

実際にはTextやImageをラップして使います。

詳しくは例によってこちら。 facebook.github.io

VrButtonの入力に使えるボタンやキー

VrButtonでクリックイベントを検知できる入力については公式ドキュメントに以下の4つが挙げられています。

  • XboxゲームパッドのAボタン
  • キーボードのスペースキー
  • マウスの左クリック
  • スクリーンタッチ

XboxゲームパッドのAボタンが挙げられていますが、他のゲームパッドでも入力を検知することができます。 ただし、必ずAボタンが対応しているというわけではなく、Gamepad APIのGamepad#Buttons配列のインデックスが0のボタンが入力ボタンとなります。

ちなみに私はWindows 環境にOculus Touchを繋いで開発しているのですが、入力ボタンはスティックキーの押し込むところになっていました。

UnityだとOculus TouchのAボタンはjoystick button 0 が割り当てられているのですが、Gamepad APIだとキーマップが違うのでしょうか。

音を鳴らす

onClickイベントを検知して音源再生のAPIを叩く…のでもいいのですが、それをやってくれる専用のpropがVrButtonには用意されています。

  • onClickSound :ボタンにフォーカスが当たっている状態でクリックした時(厳密にはボタンなどを押して離した瞬間)に音源を再生します。
  • onLongClickSound :ボタンにフォーカスが当たっている状態で長めにクリックした時(厳密にはボタンなどを押して離した瞬間)に音源を再生します。
  • onEnterSound :ボタンにフォーカスが当たった瞬間に音源を再生します。
  • onExitSound :ボタンからフォーカスが外れた瞬間に音源を再生します。

なお、ボタンを押して離したタイミングではなく、ボタン押下時に音を鳴らしたい場合は、onButtonPressイベントを検知して、音源を再生する処理を書く必要がありそうです。

具体的にはあらかじめ再生したい音源をVrSoundEffects.loadでロードしておき、VrButttonのonButtonPressイベントが検知されたタイミングで、VrSoundEffects.playを使って音源を再生するといった流れになると思います。

サンプルプログラム

それでは前置きが長くなりましたが、VrButtonのonClick, onLongClick, onEnterSound, onExitSoundを使って効果音を鳴らすプログラムがこちらになります。

import React from 'react';
import { AppRegistry, asset, Pano, Text, View, VrButton} from 'react-vr';

export default class ButtonSample extends React.Component {

    constructor() {
        super();

        this.state = {
            sound:  {
                        wav: asset('click.wav'),
                        ogg: asset('click.ogg'),
                        mp3: asset('click.mp3')
                    }
        };
    }

    render() {
        const sound = this.state.sound;
        return (

            <View>
                <Pano source={asset('chess-world.jpg')}/>

                <View style={{
                    flex: 1,
                    flexDirection: 'row',
                    width: 5,
                    alignItems: 'stretch',
                    transform: [{translate: [-2.5, 0, -5]}],
                }}>

                <SampleButton text="Click" onClickSound={sound}/>

                <SampleButton text="LongClick" onLongClickSound={sound}/>

                <SampleButton text="Enter" onEnterSound={sound}/>

                <SampleButton text="Exit" onExitSound={sound}/>

            </View>
        </View>
        );
    }
}

export class SampleButton extends React.Component {

    static propTypes = {
        color: React.PropTypes.string,
        text: React.PropTypes.string,
        onClickSound: React.PropTypes.object,
        onLongClickSound: React.PropTypes.object,
        onEnterSound: React.PropTypes.object,
        onExitSound: React.PropTypes.object
    };


    static defaultProps = {
        color: 'coral',
        text: '',
        onClickSound: null,
        onLongClickSound: null,
        onEnterSound: null,
        onExitSound: null
    };

    constructor(props){
        super(props);
    }

    render(){
        return(

            <VrButton
                onLongClick={()=>{}}
                onClickSound={this.props.onClickSound}
                onLongClickSound={this.props.onLongClickSound}
                onEnterSound={this.props.onEnterSound}
                onExitSound={this.props.onExitSound}
                style={{flex: 1}}>
                    <Text style={{fontSize: 0.2, textAlign: 'center', margin: 0.1, height: 0.3, backgroundColor: this.props.color}}>{this.props.text}</Text>
            </VrButton>
        );
    }
}

AppRegistry.registerComponent('ButtonSample', () => ButtonSample);

onLongClickSoundの再生にはonLongClickの指定が必要

仕様なのか、バグなのか、onLongClickSoundのみ、音源を再生するには対応するイベントの定義が必要です。
onLongClickで何もしないで音だけ鳴らしたいということはほとんどないかもしれませんが、そうしたい場合は上のコードのようにonLongClick={()=>{}}を指定する必要があります。

VrButtonの詳しい実装についてはこちらのソースをお読みください。 github.com

ひとこと

cluster.でReact VRとかA-Frameとかの勉強会ってやってないのでしょうか。
おうちでのんびり聴講したいです。

React VRで頭の動きに追従するカーソルを表示する

VR初心者のちらです。

今回はVRでよくある、頭の動きに追従するカーソルの表示方法についてのお話です。

まずReact VRのカーソルシステムについてのドキュメントはこちら。

facebook.github.io

カーソルの実装

カーソルはRayCasterを利用して実装します。

学生時代のおぼろげな記憶で説明をするのも良くないので、レイキャストについての詳細は割愛しますが、ちゃんと調べたい人はレイキャストとかレイキャスティングで検索をかけるといいと思います。

RayCasterで実装が必要なメソッドは以下の3つになります。

  • getType - raycasterを一意に特定できるような文字列を指定します。
  • getRayOrigin - カメラを基準にしたときの光線の原点を3次元座標で指定します。
  • getRayDirection - カメラの向きをもとに光線の方向を3次元ベクトルで指定します。

さらにオプションで2つのメソッドが用意されています。

  • frame - アプリケーションのフレーム毎に呼び出されるメソッドです。
  • drawCursor - 目に見えるカーソルを描画するかどうか決定するメソッドです。

カーソル用に各メソッドを実装するのであれば、  

  • getType : 任意の文字列
  • getRayOrigin : [0, 0, 0] カメラの原点
  • getRayDirection : [0, 0, -1] カメラの正面方向
  • frame : 実装しない
  • drawCursor : true

とするのがいいと思います。

カーソルの可視性の制御

カーソルの可視性はcursorVisibilityというオプションで制御できます。
このオプションはclient.jsやindex.htmlでの初期化の際に設定することができます。

設定できる値は以下の3つです。

  • hidden - カーソルを常に非表示にします。デフォルトではhiddenになっています。
  • visible - カーソルを常に表示します。
  • auto - 入力イベントハンドラを持つコンポーネント(など)に視線がぶつかっているときにカーソルを表示します。

autoを設定する場合も、デバッグ中はvisibleにしておくのがよさそうです。

実装

今回はアプリケーション全体でカーソルを可視化する体でclient.jsに可視化処理を実装しました。
初期化時のオプションのraycastersにカーソル用のRayCasterを実装し、同じくオプションのcursorVisibilityをvisibleにします。

// Auto-generated content.
// This file contains the boilerplate to set up your React app.
// If you want to modify your application, start in "index.vr.js"

// Auto-generated content.
import {VRInstance} from 'react-vr-web';

function init(bundle, parent, options) {

  const vr = new VRInstance(bundle, 'ReactVrSample', parent, {
     // Pass in the custom font as an initialization property
     raycasters: [
          {
            getType: () => "mycursor",
            getRayOrigin: () => [0, 0, 0],
            getRayDirection: () => [0, 0, -1],
            drawsCursor: () => true
          } 
     ],
     cursorVisibility: 'visible',
     ...options,
  });

  vr.render = function() {
  // Any custom behavior you want to perform on each frame goes here
  };
  // Begin the animation loop
  vr.start();
  return vr;
};

window.ReactVR = {init};

せっかくなのでカーソルの当たり判定も確認できるようにします。
index.vr.jsに画面上にピンクの文字列を表示して、文字列にカーソルが当たっているときには色を赤に変える処理を書きます。

import React from 'react';
import { AppRegistry, asset, Pano, Text, View } from 'react-vr';


export default class ReactVrSample extends React.Component {
 constructor() {
    super();

    this.state = {textColor: 'pink'};
  }

  render() {
    return (
        <View>
        <Pano source={asset('chess-world.jpg')}/>
      <Text
        style={{color: this.state.textColor, 
            fontSize: 0.3,
            fontWeight: '400',
            layoutOrigin: [0.5, 0.5],
            paddingLeft: 0.2,
            paddingRight: 0.2,
            textAlign: 'center',
            textAlignVertical: 'center',
            transform: [{translate: [0, 0, -3]}],
          }}
        onEnter={() => this.setState({textColor: 'red'})}
        onExit={() => this.setState({textColor: 'pink'})}>
        This text will turn red when you look at it.
      </Text>
      </View>
    );
  }  
};

AppRegistry.registerComponent('ReactVrSample', () => ReactVrSample);

確認

白い丸がカーソルです。GIFはありませんが、VRモードにして頭を動かすとちゃんと追従します。

f:id:chira_pym:20170528234908p:plain

文字の方を見ると、カーソルが文字に当たって文字の色が変わります。 f:id:chira_pym:20170528234940p:plain

ひとこと

A-Frameのtracked controllersのサンプルみたいにコントローラーの位置をトラッキングして手を表示したいのですが、公式サンプルはまだですか。

ReactVRで日本語フォントを扱う

ご無沙汰しております。ちらです。

以前からやるやる詐欺をしていたReact VRにとうとう手を出し始めました。
とは言っても、まだまだ、サンプルコード動いたー!やったー!って喜んでる段階ですが。

f:id:chira_pym:20170527131852p:plain

で、本題です。試しにサンプルコードのhello部分をはろーわーるどにしてみたのですが、こんな感じに文字化けしてしまいました。

f:id:chira_pym:20170527132352p:plain

日本語フォントをインストールしたら直ったので、備忘録として手順を残しておきます。

手順はこのドキュメントを参考にしました。
react-vr/Fonts.md at master · facebook/react-vr · GitHub

日本語フォントのダウンロード

ドキュメントを見ると、ovruiパッケージ内のfontsディレクトリに日本語フォント用のファイルが含まれているので、これを使えばいいよ的なことが書いてある気がします。

そこでまずプロジェクト直下のstatic_assetsにfontsディレクトリを作って、そこに必要なファイルをダウンロードしてきます。

必要なファイル: https://github.com/facebook/react-vr/raw/master/OVRUI/fonts/japanese.png https://github.com/facebook/react-vr/raw/master/OVRUI/fonts/japanese.fnt

client.jsを書き換える

次にドキュメントの真似をしながらvrディレクトリ内のclient.jsを書き換えます。こんな感じであってるかな?

// Auto-generated content.
// This file contains the boilerplate to set up your React app.
// If you want to modify your application, start in "index.vr.js"

// Auto-generated content.
import {VRInstance} from 'react-vr-web';
import * as OVRUI from 'ovrui';

var fallbackFonts = {
  '../static_assets/fonts/japanese.fnt': '../static_assets/fonts/japanese.png'
};

// use the embedded defaultFont and and fallbacks
var font = OVRUI.loadFont();
var count = 0;

function init(bundle, parent, options) {
  function addFallback(fallbackFont) {
    OVRUI.addFontFallback(font, fallbackFont);
    count--;
    if (count === 0) {
      // all fallbacks are loaded start the VRInstance
      // 'font' contains everything React VR needs to render <Text> elements with
      // your custom font.

      // Pass it to the boilerplate init code
      const vr = new VRInstance(bundle, 'ReactVrSample', parent, {
        // Pass in the custom font as an initialization property
        font: font,
        ...options,
      });

      vr.render = function() {
      // Any custom behavior you want to perform on each frame goes here
      };
      // Begin the animation loop
      vr.start();
      return vr;
    }
  }
  
  for (var key in fallbackFonts) {
    // allow each font to asynchronously load in parallel and start VR instance when all complete
    count++;
    OVRUI.loadFont(key, fallbackFonts[key]).then((fallbackFont) => {
      addFallback(fallbackFont);
    });
  }
}

window.ReactVR = {init};

確認

画面をリロードするとこんな感じで日本語が表示されます。やったーヾ( ・ω・)ノ

f:id:chira_pym:20170527131919p:plain

おわりに

React VRが1.1.0からバージョンが上がった際には、コードをコピペしても動かなくなる可能性があるので、その際は公式ドキュメントをご覧ください。
以上です。

esaの運用ルールについて少しだけ考えてみた( ⁰⊖⁰)

esaを使い始めた #トノコト

Boostnoteをうまく使いこなせない系エンジニアのちらです。

最近一人でesa.ioを使い始めました。

全体的にUIが使いやすく、見た目もかわいいので結構気に入っています。

あとWIPという概念がとても良いですね。

ブログとかチケットとかの文章はなんとなく綺麗に書かないといけないという強迫観念に縛られて生きているので、 アウトプットが遅くなりがちなのですが、そのあたりの心理的障壁が下がって、個人的にはすごく刺さるものがありました。

また、Chrome拡張のtsuibamiを利用すると、メモ速度が爆速になります=͟͟͞͞ (\( ⁰⊖⁰)/)
ChromeVivaldiを使っている方におすすめです。

社内のナレッジ共有にも使いたい #トノコト

社内のナレッジ共有が滞りがちなので、会社でもesaを使えたらいいなあと思っています。
でも組織で使う場合は、運用ルールが整備されていないと、せっかくのツールの良さも活かされなかったりするんですよね…

ということで、esa歴3日の素人ながら、社内でのesaの運用ルールやテンプレートについて少し考えてみました。

前提

今回運用を考える上での前提やら想定やらです。

  • 社内全体で使用する(規模は中小レベルを想定)
  • 個人の知識の共有をメインとするが、他にも社内で共有したいことがあれば、基本的に自由に投稿して良い
  • 社外秘・社内秘の情報だけは書かない
    • プロジェクト内のルールや特有の設定などに関しては、プロジェクト管理ツール(Redmineなど)に書く
    • その他、外に出せない情報は社内専用の情報共有場所(社内wikiなど)に書く
  • WebhookはEmailのみ使用

WebhookにEmailしか使わないのは、単に私が職場でチャットサービスを使ってなくて、SlackやHipChatに詳しくないからです。

カテゴリ

何をカテゴリにして、何をタグにするかを悩みましたが、とりあえずこんな感じになりました。

※PCから見たときに縦に長くなるので、技術情報の第三階層はリストにするのをやめました。

カテゴリの説明

esa Tips:
esaのTips集です。 公式のProTipカテゴリみたいなものです。

経営:
エンジニアも経営のことを知っていた方が良いとよく話を聞くので、経営カテゴリを用意しました。

不勉強なのでこれ以上階層を切れませんでしたが、きっと経理、組織論、法務あたりの情報を共有するのだと思います。

マーケティング:
Webマーケティングの情報に関するカテゴリです。
営業の人が使う想定で用意しました。

このカテゴリも詳しくないので、これ以上の階層を切っていません。
Webエンジニア的にはSEOアクセス解析についての情報が共有されるとうれしいです。

技術情報:
技術に関する備忘録、はまったこと、発見したことなどを共有するカテゴリです。
一部、カテゴリを言語で切るか、フレームワークで切るか悩みましたが、なるべく言語で切ることにしました。

他のカテゴリとの関係を考えて、言語、フレームワークは必ずタグで記述する決まりにします。
この時、タグに言語やフレームワークのバージョン番号は書かない方針にします。

面倒がって書かない人がいるでしょうし、バージョンが関係する情報はその旨がドキュメント内に書かかれるはずなのでそれで良いかなという判断です。

QAコーナー:
QAコーナーはStack Overflow的なカテゴリです。
ここに記事が投稿されたらメーリスに通知するようにしておきます。

内容が解決したら、アーカイブするか、技術情報のカテゴリへ移します。

社内チャットなど、すでにナレッジコミュニティが他にあるなら、このカテゴリは無くてもいいと思います。

イベント:
技術展や勉強会といったイベントに関する情報を共有するカテゴリです。

イベントを主催するときのお知らせや参加レポを共有します。 開催情報のカテゴリに記事が投稿されたらメーリスに通知するようにしておきます。

書籍:
最近読んだ技術書やビジネス書などの情報を共有するカテゴリです。 本の概要や内容に関するメモ、所感を書いて共有します。

ドキュメントを書こうと思った本のドキュメントが既出の場合は、コメントにメモや感想を追記します。

これ以上、下の階層を増やすどうか悩みましたが、とりあえずタグを使った運用にして、ドキュメントが増えてきたらカテゴリを増やせばいいと思います。

ポエム:
ここでいうポエムとは以下のような文章を指します。

ビジネス文章としての整合性や第三者からの検証性を必ずしも重視せず,書き手自身の理想であったり熱意だったり危機感だったり,そういう何らかの感情の発露を自分の中で反芻してとりまとめた表現した文章や図面の事。規模は数行から数十行であることが多い。
第1回 事業会社における開発とポエム:会社で「ポエム」を綴ろう! ~ポエム駆動で理想を語ると社内の風が変わる!~|gihyo.jp … 技術評論社 

ポエム駆動型開発を取り入れないにしても、こういうのを吸い上げられる場所って大事だと思うんですよね、というポエム。

雑記:
これまで紹介したどのカテゴリにも属さないドキュメントを共有するカテゴリです。

どのカテゴリに置いてよいかわからないドキュメントは、ひとまずここに書いておいて、 あとで新しくカテゴリを増やすなり、既存のカテゴリに移すなりするといった運用もできます。

テンプレート

ドキュメントをさくっと書けるように、必要事項を埋めるだけで良いようなテンプレートを用意してみました。

インストール手順テンプレート

f:id:chira_pym:20170320014119p:plain

#:raised_hand: 前提

### :dvd: インストールするソフトウェアとバージョン  
piyo 1.0

###  :computer: OS  
Windows 10

### :cd: 事前にインストールが必要なソフトウェア
なし

# :memo: 手順
1. hoge
2. fuga

#:warning: 注意点

イベント案内テンプレート

f:id:chira_pym:20170320041825p:plain

# :information_source: 基本情報

:calendar:  日時 : 
 
:office:  会場 : 

:black_nib:  テーマ:

# :scroll: 概要

URL: http://google.com

イベント参加レポテンプレート

f:id:chira_pym:20170320040939p:plain

# :information_source:  基本情報

:calendar:  日時 :
 
:office:  会場 :

:black_nib:  テーマ:

# :scroll: 概要

# :thumbsup: 良かった発表・勉強になったことなど  

# :books: 資料
<!--
このようにSlide Shareのスクリプトを埋め込むことができます。
<script async class="speakerdeck-embed" data-id="5633a9b0599d01326f2b4e55f5ecb48c" data-ratio="1.41436464088398" src="//speakerdeck.com/assets/embed.js"></script>
-->
# :coffee:   所感

書籍テンプレート

f:id:chira_pym:20170320133311p:plain

# :blue_book: タイトル

# :scroll: 概要

# :memo: メモ
<!--
読んだことに関して、何かメモしておきたいことがあれば記入してください。
-->

# :coffee:   所感

# :clipboard:  アンケート(任意)

**評価** : :star: × n

## 良かったこと
なし

## 良くなかったこと
なし

## どんな人におすすめか
なし

最後は管理者が頑張るしかない #トノコト

なるべく人が悩む要素はつぶしましたが、それでも、この構成でAWSやDocker関連のドキュメントはどこにどう書こうか、自分でも悩むので、まだまだわかりにくいカテゴリルールになっていると思います。

また、タグの付け方のルールをしっかり定義していないので、そのあたりに起因する問題も起きそうです。

ということで、実際に運用したわけではありませんが、運用時には以下のことが想定されます。

  • カテゴリやタグが乱立する
  • ドキュメントに期待するタグをつけてもらえない
  • ドキュメントが重複する

もともと情報が育ったら整理することを前提としたサービスなので、週1、あるいは月1でドキュメントを整理する時間を設けて、その時にこういったドキュメントの整理もした方が良さそうです。

その時に、それこそドキュメントの整理時のルールを共有するようにしたら良いのではないかと思います。

所感

遅筆なのでここまで書くのに体力と時間をかなり持っていかれました。
お昼寝して起きたら、もっとすごい人たちのちゃんとした記事が上がってるに違いないです。

それではおやすみなさい(:3[___]

MariaDBを削除したらPostfixも一緒に消えちゃった話

会社で休眠状態になってるサーバーを上手いこと活用すべく、色々なツールを入れていたところ、気付いたらそのサーバーからメールが飛ばなくなっていました。

maillogを見てみるとそもそもPostfixが動いていないようでした。 先週まで元気に動いてたはずなのにおかしいなと思いつつ、起動させようとしてみました。すると「postfix.serviceは存在しません」みたいなことを言われました。

…このサーバーを立ち上げる時にPostfixを入れて、四苦八苦しながら設定作業をしたのは私のはずですし、そもそも先週まではちゃんと動いていたはずなのですが、これは一体😓

念の為、こんな感じのコマンドでサービス一覧を出してみましたが、postfix.serviceは見当たりませんでした。

$ systemctl list-unit-files --type=service

結果は貼れませんが、Dovecotとかはちゃんといました。一体Postfixはどこへ… 嫌な汗をかきつつ、whichコマンドを打ちます。

$ which postfix
no postfix in ...

見つかりません。 間違いなくPostfixが入ってるはずなのに… 混乱した頭でyumのインストール済みのパッケージの一覧を出します。

$ yum list installed | grep postfix

何も返ってこない😨

半ば祈る気持ちでfindコマンドを打ちます🙏

$ find / -name postfix
/etc/postfix

…設定ファイルのディレクトリはありました。 実は全てが自分の気のせいで、そもそもPostfixなんて入ってなかったオチとかじゃなくて良かったです😅

ここで少し落ち着きを取り戻して「postfix 消えた」という、大変ざっくりしたキーワードでググり始めました。 こんな雑な検索でも、このような記事が引っかかってくれました。

[Postfix]そうだったのかキミはMySQLと関係を持っていたのか![Postfix]そうだったのかキミはMySQLと関係を持っていたのか!

こんにちは。パッケージの削除について考えらされたので記事にしました。こちらのエントリーで構築した環境でメールテストを行った際に発覚しました。[ローカル開発環境 ...

この記事だとMySQLを更新するのにremoveしたところ、Postfixも削除されてしまったそうなのですが、ずばり私もMariaDBのアップデートをするのに、それまで使ってたバージョンを削除していました。

つまりPostfixを削除した犯人は私だったのです…!

うん、そんな気はしてた。そんな気はしてたけど…!そんな…!!

こう、推理小説とかで、主人公が実は犯人だったみたいな展開って、はたから見るとすべってることも多いのですが、いざ体験してみると、ものすごくびっくりするんですね。今すごく読者との温度差を感じます。

気を取り直して、先ほどの記事にあるように、yum historyを確認します。

$ yum history list | grep Erase

Eraseになってる直近の履歴が出力されるので、あとはちまちまとyum infoで確認していきました。

$ yum history info 20

これも結果は貼れませんが、切り替えたパッケージの項目に「削除 postfix …」と書かれているものが見つかりました。

さらにスクリプトの出力の項目を見てみると /etc/postfix/main.cfや/etc/postfix/master.cf, /etc/postfix/virtualはバックアップが保存されている旨の警告が出ていました。 今回はよりにもよって物理サーバーでやらかしたので、ものすごくげんなりしていましたが、設定ファイルが無事となれば、すぐに元の状態に戻せそうです。

意気揚々とPostfixを再インストールしなおします。

$ yum install postfix

やらかしたばかりなので、yオプションはつけませんでした。でも明日辺りには、また軽率にオプションをつけていく生活に戻る気がします。

あとは警告で出ていた設定ファイルたちを元の場所に戻します。

$ rm -f /etc/main.cf
$ mv /etc/main.cf.rpmsave /etc/main.cf

/etc/postfix/virtualを設定しているので、postmapコマンドも打っておきます。

$ postmap /etc/postfix/virtual

これでなんとかメールサーバーを復旧させることができました🙌