それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

コマンドでword/excel/powerpoint のファイルをPDFに変換する。

Libreoffce のコマンドを使うと変換が楽

libreoffice には libreoffice(旧名 soffice) コマンドが付属していて、コレを使うことで、doc/docx xls/xlsx ppt/pptx をPDFに変換することが出来るのです。

libreoffice --convert-to pdf --outdir $dest_dir --headless $file_name

リモートでXなしのばあい

ssh 経由で x11 ログインしていない場合は、エラーになるので xvfbを使います。

xvfb-run libreoffice --convert-to pdf --outdir $dest_dir --headless $file_name

xvfb は X11 Virtual frame buffer のことですね。コレを使うことで、リモートのLinuxのXを使ってLibreoffice経由で、Officeファイルが変換できるわけです。

ズレる場合の対処法

PPTXなど、コンバート後のPDFズレる場合の対処。 とくにPowerPointのファイルに顕著に現れるのですが、表示がずれる場合が多かった。この状況の対処方法を検討したら、次のことがわかった

  • LibreOffice の最新版を「提供元」から導入する
  • フォントを大量に突っ込む

この解決策を試みた所、MS-Officeと遜色ないPDFが生成されるようになった。

Libreofficeの最新版をいれる事について

最新版で互換表示の相当量が改善されています。そのため、Linuxディストリビューションが提供するパッケージより、Libreofficeの提供元から最新版を導入したほうが互換表示の面では有利でした。

もちろん、APTを無視して、deb / rpm などの最新版を入れると、管理が面倒なのですが。

フォントを入れる

ライセンス的にはあまり関心しないけれど、MSゴシックなどを、LibreOfficeの動く、Linux変換サーバー側に用意すると、相当改善します。

Preview.appでズレるのも同じ

この事象にアタックして気付いたのですが、macOS X のプレビューでOfficeの表示は、Libreofficeのそれと「全く同じようにズレる」のです。

Mac OSXには、プレビュー.app という超絶便利なプレビューがあるのですが、 これが、どうしても「ずれる」のです。

このズレが、Libreofficeの旧版やフォント無し状態と同じずれ方なのです。

ここから、想像するに、プレビュー.app は LibreOfficeのエンジンを使ってると思われます。(しかも古い)

なので、Preview.appで表示がおかしいと思うときは、Libreofficeをプレビュー代替につかってQuickLookに登録すると嬉しいかもしれません。今度試してみたい

圧縮形式や文字化けを問わず解凍出来る unar/The Unarchiverを知った。

unar コマンドを教えてもらいました。

unar コマンドは、The Unarchiverのコマンドで、かなりの圧縮形式に対応している。

WinRARみたいなもんだと思ってた。MacOS X 買った時に、コマンドメインで行こうと考えていたので、スルーしていました。

The Unarchiverには unar コマンドが付随していて、とても便利なんですね。

unar コマンドが、大抵の圧縮形式の展開(解凍)を問題なくやってくれるし、文字コードも問題ない。何でも使える。

インストール

mac OS X

brew install unar

Finderから使える.app も入れるなら

brew cask install the-unarchiver

Debian/GNU Linux

sudo apt install unar

特徴

  • カナリのフォーマットに対応
    • zip はもちろん rar / 7z
    • tar だけじゃなく msi にも
  • 文字コード検出がマシ
    • 文字コードによる化けが起きづらい(起きないとは言えない)
  • unar と対になるlsarがある。

lsar : アーカイブに含まれるファイル一覧

unar とペアで使うのが lsar

lsar sample.zip

このコマンドで、中身のファイルを一覧できる

unar :何でも展開できるコマンド

とりあえず、覚えておけば、他のコマンドを覚えなくて済むツール。

unar sample.zip

コレさえアレば、全てコレでやってしまいそうな麻薬みたいなツール。tar / zip コマンドの扱いを忘れそうなので、Linux初心者に教えるわけにはいけない。。。。

自分のグローバルIPをチェックする方法について

コマンドラインで自分のグローバルIPをチェックしたい。

コマンドライングローバルIPを取得して、今のIPを確認して保存したい。

必要なもの

  • xmllint または jq
  • curl

curl で取得して、xpath で切り出す感じ

グローバルIPの取得

curl -s http://www.myglobalip.com/ | xmllint --html --xpath  '//*[@id="default"]//text()' -

準備

curl がないって環境は存在しないだろうけど、xmllint はない場合はインストールする。

sudo apt install libxml2-utils

ubuntu/debian の場合はこれでxmllint という超絶便利なコマンドが入手できる。

alias

alias 化しておかないとふべん

alias xpath="xmllint --html --xpath"

取得するサイトを変えてあれこれ試す。

json で取得できるサイトを使う

xpath の場合

 curl https://www.cman.jp/network/support/go_access.cgi -s   | xpath '//*[@class="outIp"]/text()' -
curl -s http://www.displaymyip.com/   | xpath '//*[@class="ip"]/text()' -

jq の場合

 curl -s  http://httpbin.org/ip | jq -r  .origin
curl -s  'https://api.ipify.org?format=json' | jq -r  .ip

jq も xmllint も無いって人は

curl inet-ip.info

スクリプトから グローバルIPをチェックしたい時の注意事項

老舗を使え、HTMLのデザインが古い奴を選べ、ちゃんと10年以上安定化移動している証拠だ。

HTMLのデザインが古いのは、たぶんみんなスクレーピングしてるから。

最近のデザインのものは、すぐにサービス停止したり、気まぐれでドメインが失効したり。対応が面倒くさい。

企業は倒産するかもしれないので個人のものより寿命が短い傾向がある。

出来る限り長く稼働して居るものが安定です。

ドメイン名の有効期間を調べて長く使えるものが良いでしょう

特に注意するもの、ドコかの企業が運営してるもの、ブロガーが運営してるものは多分数年内に消える。面倒くさいですよね。

自宅鯖運営民にとってグローバルIPが自動更新されなくなると死活問題ですから。

2022-04-04

エイリアスについて更新

tar から一部のファイル・指定ファイル名だけ、標準出力(stdout)へ、など各種指定してきれいに取出す方法。

tar ball を渡されて困る。

毎回毎回展開するのダルいんだよ。欲しいファイルや見たいファイルは一つだけ、もしくは複数ファイルだったりする

tar tvzf で中身を見る

tar で中身を見るには tvf ・ tvzf を使う z は gzip

tar tvzf test.tgz
drwxr-xr-x takuya/staff      0 2016-07-25 19:59 テスト/
-rw-r--r-- takuya/staff      0 2016-07-25 19:59 テスト/テスト1
-rw-r--r-- takuya/staff      0 2016-07-25 19:59 テスト/テスト2
-rw-r--r-- takuya/staff      0 2016-07-25 19:59 テスト/テスト3
-rw-r--r-- takuya/staff      0 2016-07-25 19:59 テスト/テスト4
-rw-r--r-- takuya/staff      0 2016-07-25 19:59 テスト/テスト5
-rw-r--r-- takuya/staff      0 2016-07-25 19:59 テスト/テスト6
-rw-r--r-- takuya/staff      0 2016-07-25 19:59 テスト/テスト7
-rw-r--r-- takuya/staff      0 2016-07-25 19:59 テスト/テスト8
-rw-r--r-- takuya/staff      0 2016-07-25 19:59 テスト/テスト9

指定したファイルを取出す

tar  x -f test.tgz 'テスト/テスト1' 

この方法で取出すことが一般的であると思う。でも、この方法ではファイルだけでなく、フォルダ構造も再現さしてくれる。ファイルだけ中身を見たい時にちょっと不便だと思う。

指定したファイルを取出す。標準出力へ。

指定したファイルを取出す。

tar  x -f test.tgz 'テスト/テスト1'  -O

tar には -O というオプションが合って、コレを使えば、指定したファイルを標準出力に取り出すことが出来る。マジか便利だ。

指定したファイルに取出す

ディレクトリ構造を作られるのがめんどうなので、標準出力をリダイレクトすることで、指定したファイルに取出すことが出来る。

tar  x -f test.tgz 'テスト/テスト1.jpg'  -O out.jpg

これで、tar ファイルの取扱が数段楽ちんになる。

ファイルの中身をみて、その結果をパパッ取り出せるなら、イチイチ展開してcd てたどっていくの面倒だし、作業用ディレクトリを作るの面倒なんだよね。

指定したフォルダへ展開

最初にフォルダを作るのが必須

mkdir 04-25
tar xf  etc-2023-04-25.tgz  -C 04-25

指定したファイルを指定したフォルダへ( オプション -C 版)

-C を使った場合の例

mkdir 04-25
tar xf  etc-2023-04-25.tgz /etc/pam.d/common-auth  -C 04-25

これで動くはずなんだが。ディレクトリの場合はなぜか動かない。

寸感

参考資料にあるように GNU tar での動作を確認しています。

私は、GPL信者なのでGNU tarを利用しているので、コレで動かすことが出来ました。

BSDのtar のman を見ても出来るようなので、大丈夫でしょう

っていうか tar ってgnu tar 以外にあるんだろうか。。。

参考資料

https://www.gnu.org/software/tar/manual/html_node/Writing-to-Standard-Output.html

http://www.freebsd.org/cgi/man.cgi?tar(1)

find コマンドで所有者やグループが条件マッチするファイルを探す

指定ディレクトリの下に、オーナがオカシイファイルが出来る

php などWEBアプリが、ownerをちゃんと設定してくれなかったり、グループを設定してくれなかったり。

また、crontab がroot で動いていて消せないファイルが出来たり。

もちろん、ソースコードを直すのが先決。

ソースコードを直すのが先決だし、ディレクトリにStickyBitやSGIDを立てるのがより推奨されるけれど。

できちゃったファイルを探すには

すでに作成されたファイルを探すにはどうするか。

ファイルが既に作られちゃったのを探すには、find コマンドを使うのが便利

指定したグループになってるファイルを列挙する

find ./ -group root

あるユーザーになっているファイルを探すにな

ファイルのownerがユーザーになっているファイルを探すには。

find ./ -user root

あとは xargs と組み合わせて

chmod するなり、chown するなり、rm するなり。

また、ディレクトリを探す、ファイルを探すと組み合わせて戦う

関連資料

find コマンド関連の他の記事はこちら

参考資料

man find

linux ユーザをグループに追加・削除する gpasswd 編

ユーザーをグループに追加したり削除するには

  • usermod
  • gpasswd
  • vigr

の3種類のコマンドが有ります。

何方を憶えるべきか、何方を使うべきか。迷うところですね。

今回は gpasswd を使ったユーザーの管理をまとめておくことにします。

gpasswd の使い方

gpasswd コマンドでユーザのグループ所属を変えることが出来ます。

ユーザーをグループに追加するには

gpasswd -a  takuya www-data

グループからユーザーを除外する

gpasswd -d takuya www-data

オプション -d で指定ユーザを削除します。

gpasswd が有利なポイント

gpasswd GROUP -a username

オプションの引数にユーザー名を入れる点。これでミスが減りやすいし、グループに対して◯◯すると明確なので、ユーザーのプライマリグループをウッカリ変えてしまうことがなくて助かります。

gpasswd コマンドを使うメリット

gpasswd コマンドは、引数(グループ・ユーザー)の区別が明確でミスが少ない。オペミスすると即死する系では非常に友好的に使えるはず

usermod を覚えておくメリット

gpasswd があるなら usermod いらないよね?ってそんなこともない。

gpasswd は GNU/Linuxに存在するコマンドですね。macOS XBSD のようなシステムには存在しない。

より汎用的なのは usermod だといえます。*1

またusermod は user に関するあれこれを変更できるので、使う機会が多いです。まとめてメモに残して覚えやすいですね。

Linuxしか使わねーよって人であればソレでも良いかもしれませんが。。。。

関連資料

usermod を使った場合はこちら。

Linuxユーザーをグループに追加する方法(追記:まとめて複数グループに追加 - それマグで!

*1:* 手元のOSXには入ってませんでした

chroot環境下でホスト側のデバイス/devなどを使う。

/dev などをホスト側と共通にする

chroot 環境って、あれこれ試したい時に便利なんですよね。

grub を作りなおしたり、ビルドしたい時にたまに使うんだけど、chroot ってなんかこう、思い通りに行かない時があって。

たとえば イメージディスク中にあるものを触りたい

mount -o loop してイメージディスク中にある、イメージをあれこれ調整したい時があります。

今回は ディスクイメージ中のgrubを触ろうと思った。

ほかにもディスクイメージ中のraid構成をfstab をチェックしたいとかそういうとき、必要でした。

# cd /mnt/new-raid
# mount -t proc proc proc/
# mount -t sysfs sys sys/
# mount -o bind /dev dev/
# mount -t devpts pts dev/pts/
# chroot /mnt/new-raid

コピペ用

sudo mount -t proc proc proc/
sudo mount -t sysfs sys sys/
sudo mount -o bind /dev dev/
sudo mount -t devpts pts dev/pts/

mount してchroot 環境に持っていく

ホスト側(元)からChroot側(マウント先)へmoount を移動するだけでした。

  $ sudo mount /dev/sdXZ /mnt
  $ sudo mount /dev/sdXY /mnt/boot/efi
  $ sudo mount --bind /dev /mnt/dev
  $ sudo mount --bind /dev/pts /mnt/dev/pts
  $ sudo mount --bind /proc /mnt/proc
  $ sudo mount --bind /sys /mnt/sys
  $ modprobe efivars
  $ sudo chroot /mnt

  # grub-install /dev/sdX
  # update-grub
  # exit

  $ sudo umount -lf /mnt/sys
  $ sudo umount -lf /mnt/proc
  $ sudo umount -lf /mnt/dev/pts
  $ sudo umount -lf /mnt/dev
  $ sudo umount -lf /mnt/boot/efi
  $ sudo umount -lf /mnt

/dev/ /proc って単なるマウント

じつは、/procファイルシステムや /dev/ ってたんにマウントなんだって事に気づいて目からうろこだった。

なるほどー!!

Linuxシステムにおけるマウントって便利すぎる概念ですね。

追記 2016-11-05

chroot でナニするんだコレって思いながらメモしましたが、最近 grub-install で頻繁に使ってます。

for i in dev proc sys ; do sudo mount /$i /mnt/target/$i;done
sudo chroot /mnt/target
grub-install ......
exit
for i in dev proc sys ; do sudo umount /mnt/target/$i;done

EFIパーティションを作ってインストールするときにテンプレのように叩いてます。

2022-01-07

誤字修正

参考資料

http://www.webzoit.net/hp/it/internet/homepage/env/cs/bootstrap/multiboot/usb_memory_stick/usb_gpt_grub2/howto/grub2-install/

http://www.ibm.com/developerworks/jp/linux/library/l-lpic1-102-2/

https://wiki.gentoo.org/wiki/GRUB2/ja#.E3.83.96.E3.83.BC.E3.83.88.E3.83.AD.E3.83.BC.E3.83.80.E3.83.BC.E3.81.AE.E3.82.A4.E3.83.B3.E3.82.B9.E3.83.88.E3.83.BC.E3.83.AB

https://wiki.ubuntulinux.jp/UbuntuTips/Others/ReinstallGrub2 https://wiki.ubuntulinux.jp/UbuntuTips/Others/ReinstallGrub2

http://www.nslabs.jp/raid1-convert.rhtml

C++のクラスの作り方の基本サンプル

C++でAnimalを作るとどうなるのかを、基本的なサンプルを使って調べてみた。

クラスの作り方

class Animal {

  protected:
    std::string  voice;
    Animal(){
    }
  public:
    void say(){
       printf( "%s\n",  this->voice.c_str()  );
    }
};

クラスの継承

クラスの継承は、こんな感じになるらしい。

class Cat : public  Animal {
  public : Cat(){
    voice = "にゃ-";
 }
};

インスタンス化とポリモーフィズム

        Animal *ani;
        ani = new Cat;

ふむ。なるほど。

cpp まだよくわからないけど

基本的なことがわかれば少しはかけるようになるかもしれない。

ただ、Win32とかあのへんのCPPは型が多すぎてかんたんには手に負えない。

全てをまとめるとこんな感じ?

ちょっとしたことも書けないとダメだよね・・・・

#include <stdio.h>
#include <string>

class Animal {

  protected:
    std::string  voice;
    Animal(){
    }
  public:
    void say(){
       printf( "%s\n",  this->voice.c_str()  );
    }
};
class Cat : public  Animal {
  public : Cat(){
    voice = "にゃ-";
 }
};
class Dog : public  Animal {
  public : Dog(){
    voice = "わんわん";
 }
};
class Lion : public  Animal {
  public : Lion(){
    voice = "がおー";
 }
};

int main( void ) {

    char str[256];
    int ret ;
  while(1){
    printf("動物(いぬ,ねこ,ライオン)  or exit? ");
    ret = scanf("%s", str);
    if ( ret == EOF ){
      break;
    }
    if (
        strcmp( "ネコ", str ) == 0 ||
        strcmp( "ねこ", str ) == 0 ||
        strcmp( "neko", str ) == 0 ||
        strcmp( "cat", str ) == 0 ||
        strcmp( "Cat", str ) == 0 ||
        strcmp( "CAT", str ) == 0
        )
    {
        Animal *ani;
        ani = new Cat;
    }
    else if (
        strcmp( "いぬ", str ) == 0 ||
        strcmp( "イヌ", str ) == 0 ||
        strcmp( "inu", str ) == 0 ||
        strcmp( "dog", str ) == 0 ||
        strcmp( "Dog", str ) == 0 ||
        strcmp( "DOG", str ) == 0
        )
    {

      Animal *ani;
      ani = new Dog;
      ani->say();
    }
    else if (
        strcmp( "らいおん", str ) == 0 ||
        strcmp( "ライオン", str ) == 0 ||
        strcmp( "lion", str ) == 0 ||
        strcmp( "Lion", str ) == 0 ||
        strcmp( "LION", str ) == 0
        )
    {

      Animal *ani;
      ani = new Lion;
      ani->say();
    }

  }

  printf("\n");
  return 0;
}

binding.pry で止まるのを止める。ループを一気に抜けて強制終了!

binding.pry 便利すぎて書きまくったら地獄だった。

pry で binding.pry を使いまくるのですが、binding.pryをループ中で使うと大変なことになる。

loop {
  binding.pry
}

抜けられない・・・

each/mapなどの loop 中でpry すると抜けらないのですが、これを手軽に強制終了する方法があります。

exit!

ruby といえばビックリマーク・エクスクラメーションマークです。pryでもコレを使えばいいんです。

pry >>> exit! 

これで手軽に抜けられることがわかって。とても快適。

参考資料

binding.pry 使ってる時に、一気にループを抜ける方法 - scramble cadenza

パーティションを含むディスクイメージをloopデバイスにマウントする。

ディスクイメージをマウントする

ただし、ディスクイメージにはパーティションが複数含まれる。

随分と前に、設定してたので、久しぶりにやろうとしてハマったので、改めて書き直し

簡単な方法

mount 時に offset を指定する。でも面倒くさいので、今回は loop0p1 みたいな指定を扱いたかったんですね。

loop デバイスを経由するパーティションを扱う場合

loopデバイスがさらに、パーティションを扱えるように、loop の設定を変える必要があった。

/etc/modprobe.d/loop.conf

modprobe の設定を以下のように追加した。

options loop max_part=63 max_loop=8

modprobe をする

sudo rmmod loop
sudo modprobe loop

losetup で loopデバイスを設定する。

dd したイメージをlosetup でつなぐ

cd 
sudo losetup -f out.img

結果を確認。

losetup
NAME       SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE
/dev/loop0         0      0         0  0 /home/takuya/out.img

パーティションを確認

これで、パーティションを見えるし扱えるようになる。

$ ls /dev/loop0*
/dev/loop0  /dev/loop0p1  /dev/loop0p2

もし見えないときは、明示的にパーティション認識のオプションを付けてあげる。

losetup -P  out.img

なぜか、明示的な- P が必要な時があって。これをつけないとパーティションを認識されないことがあるようです。違いがよくわかってない。

mkfs でファイルシステムを作ることも出来る。

$sudo mkfs.ext4 /dev/loop1p2
mke2fs 1.42.12 (29-Aug-2014)
/dev/loop1p2 contains a ext4 file system
    created on Fri Jul 15 13:45:18 2016
Proceed anyway? (y,n) y # テストなので強制上書き
Discarding device blocks: done
Creating filesystem with 91136 1k blocks and 22848 inodes
Filesystem UUID: 8df6ad88-747b-4744-b782-22098f3a5edd
Superblock backups stored on blocks:
    8193, 24577, 40961, 57345, 73729

Allocating group tables: done
Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

マウントも出来る

sudo mount /dev/loop1p2 ./mnt

マウントできるので随分楽

パーティションを指定してマウントできる。パーティションを指定出来るようになるのでほんとうに便利。

もっと良いやり方ないのかな。

ハードディスクのバックアップのマウントは結構頻出の作業なので、最初からloopデバイスで扱えればいいんだけどmodprobe する以外にないのかなぁ。

2020-11-16

-P オプションに言及

関連資料

http://takuya-1st.hatenablog.jp/entry/2014/12/12/202139

参考資料

https://stackoverflow.com/questions/37227233/having-losetup-read-the-partition-table

PowerDNSでDNSサーバーを作る。

PowerDNS 通称 pdns が便利。

pdns が便利そう。なので使ってみてる。

Power DNS で出来ること

PowerDNSはDNSで出来ることが一通り全てできる。

  • 権威サーバー
  • ミラーサーバー
  • キャッシュサーバー

これらをちゃんと実装している。

さらに、コンテンツサーバーについては、ゾーンとレコードをSQLバックエンドに放り込むことが出来る。

SQLでバックエンドに放り込めるだけでもすごいのに

  • bind
  • mydns
  • tinydns

これらのファイル形式に対応してて、レコードを様々な形で持つことが出来る。いいな、これ。

あと、LDAPに格納したレコードも使えるらしい。無敵か。

さらにHTTP機能がある。

WEBサーバー機能があって、PowerDNSのモニタリングができて、HTTP APIまでもがついてくる。

インストールして使ってみる。

インストールに必要なものと、インストールした環境

こんかいはCentOSを引っ張り出してきた。

準備 : 1

DNS を扱うのでDNSを扱うのに必要な dig コマンドを用意しておく

sudo yum install bind-utils

dig いれたら準備段階として dig の結果とネットワーク疎通を見ておく

dig +short t.co

その他に bash-completion nmap vim-enhanced などを入れた

準備 : mysql をインストール

mysql サーバーにDNSレコードを作ることにするので、MySQLを準備してくる

sudo yum install mysql-community-server

mysql のroot の基本設定をしておく

sudo mysql_secure_installation

MySQLにユーザーとデータベースとテーブルを準備する。

MySQLをインストールしたので、ユーザーを作る

create user 'pdns'@'%' identified by 'password'; 

MySQL に pdns のデータベースを作る。

もう管理が面倒くさいのでユーザー名と同じにした。

create database pdns;

pdns ユーザーにデータベースの権限をGRANTする

grant all on pdns.* to 'pdns'@'%'

一通りがおわったら、flush しておく

flush privileges;

pdns ユーザーでログインしてみる

mysql -u pdns -p 

ログインできたら権限をチェックしておく

use pdns

データベースにテーブルを作る

CREATE TABLE domains (
  id                    INT AUTO_INCREMENT,
  name                  VARCHAR(255) NOT NULL,
  master                VARCHAR(128) DEFAULT NULL,
  last_check            INT DEFAULT NULL,
  type                  VARCHAR(6) NOT NULL,
  notified_serial       INT DEFAULT NULL,
  account               VARCHAR(40) DEFAULT NULL,
  PRIMARY KEY (id)
) Engine=InnoDB;

CREATE UNIQUE INDEX name_index ON domains(name);


CREATE TABLE records (
  id                    INT AUTO_INCREMENT,
  domain_id             INT DEFAULT NULL,
  name                  VARCHAR(255) DEFAULT NULL,
  type                  VARCHAR(10) DEFAULT NULL,
  content               VARCHAR(64000) DEFAULT NULL,
  ttl                   INT DEFAULT NULL,
  prio                  INT DEFAULT NULL,
  change_date           INT DEFAULT NULL,
  disabled              TINYINT(1) DEFAULT 0,
  ordername             VARCHAR(255) BINARY DEFAULT NULL,
  auth                  TINYINT(1) DEFAULT 1,
  PRIMARY KEY (id)
) Engine=InnoDB;

CREATE INDEX nametype_index ON records(name,type);
CREATE INDEX domain_id ON records(domain_id);
CREATE INDEX recordorder ON records (domain_id, ordername);

テーブル構造の詳細は公式ドキュメントにある。今回は、domains/zonesさえアレば動くので、これだけ持ってきておいた。

っていうか。テーブル構造は全然うるさくない。自分で適当なテーブルで作ってもいいし、名前をマッピングしておけばちゃんと動くらしい。好きなカラム追加しても良い。緩さがいいよな。使いやすい。

MySQL以外にSQLitePostgreSQLを使う時もほぼ同じだと思う。

pdns のインストール

準備が終わったので、pdnsをインストールすることにする。

sudo yum install pdns

さらに、mysql をバックエンドに使うので mysql-backend をインストールしておく。

sudo yum install pdns-backend-mysql

pdns の設定: mysql

mysql を使うように設定するので

launch=gmysql
gmysql-host=127.0.0.1
gmysql-user=pdns
gmysql-dbname=pdns
gmysql-password=XXXXXXXXXXX

これを書いた。

その後

service pdns restart

接続の確認

nmap localhost 

53 番が空くことを確認

dig example.com @127.0.0.1

とりあえず接続して応答は返ってくることを確認。もちろんレコードは何もない。

レコードの追加

サーバーが起動したのでレコードを追加する。

mysql のデータベースにDNSゾーンとDNSレコードとしてテーブルにレコードを追加する。

mysql -p -u pdns pdns 

接続できたら、SQLで流し込む。

INSERT INTO domains (name, type) values ('example.com', 'NATIVE');
INSERT INTO records (domain_id, name, content, type,ttl,prio)
                      VALUES (1,'example.com','localhost ahu@ds9a.nl 1','SOA',86400,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
                      VALUES (1,'example.com','dns-us1.powerdns.net','NS',86400,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
                      VALUES (1,'example.com','dns-eu1.powerdns.net','NS',86400,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
                      VALUES (1,'www.example.com','192.0.2.10','A',120,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
                      VALUES (1,'mail.example.com','192.0.2.12','A',120,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
                      VALUES (1,'localhost.example.com','127.0.0.1','A',120,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
                      VALUES (1,'example.com','mail.example.com','MX',120,25);

これで、example.com のNSにwwwを登録することが出来た。

問合せてみる

これで完成なので、早速問合せてみる。

 dig example.com any  @127.0.0.1

; <<>> DiG 9.9.4-RedHat-9.9.4-29.el7_2.3 <<>> example.com any @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36246
;; flags: qr aa rd; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 2
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1680
;; QUESTION SECTION:
;example.com.           IN  ANY

;; ANSWER SECTION:
example.com.        120 IN  MX  25 mail.example.com.
example.com.        86400   IN  NS  dns-eu1.powerdns.net.
example.com.        86400   IN  SOA localhost. ahu.ds9a.nl. 1 10800 3600 604800 3600
example.com.        86400   IN  NS  dns-us1.powerdns.net.

;; ADDITIONAL SECTION:
mail.example.com.   120 IN  A   192.0.2.12

;; Query time: 6 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu Jul 14 20:15:11 JST 2016
;; MSG SIZE  rcvd: 189

うん、ちゃんと応答する。

HTTP のAPIを準備する。

ちゃんと応答したので、手軽に更新するために curl から叩いたら便利だよね。

MySQLをレコード使えば更新できるので、RailsMySQL更新するAPIを作っても良いんだけど、最初からあるなら、ソレ使ったほうが楽だよね。

HTTPのAPIを準備する。

webserver=yes
webserver-address=127.0.0.1
webserver-port=80

##
experimental-json-interface=yes
experimental-api-key=changeme
experimental-logfile=/var/log/pdns.log

とりあえず、WEBSERVERをつけたら、状態をモニタリング出来るようになってる。

json-interfaceをオンにしたら、WEB-APIが解放される。楽ね。

API を叩いてみる。

curl -H 'X-API-Key: changeme' http://127.0.0.1:80/servers/localhost/zones 

これだけ!あーカンタン。幸せ。

APIはなんでもできるから管理をしっかりしないといけない。

まとめ

最近、ダイナミックDNSが軒並みシンドイ事になってきた。

ダイナミックDNSスパマーがIPをコロコロ変えるのに利用されたり、クラウドの普及で需要が減ったりしてる。そのため何処も収益化に必死になってきた。

たいへん不自由なので、自分でDNSサーバを作ったほうが良いと判断しました。

DNSの管理は大変だし、乗っ取られたら大変なので注意が必要だし、いろいろと考えることが多い。

でもDNSを自分で管理できるととても便利だし、クラウドが手軽に使えるのにDNSを自由に使えない。結局は、DNSが使い勝手や手軽さのボトルネックになってしまう。

お名前.com のようにTTLが長すぎて変更に時間がかかったり value-domain のように変な挙動する dns だったり。もうね。

GoogleAmazonのサービスはちゃんとDNSが基本セットに入ってるんだよ。DNS手軽に使えないのものをクラウドと読んでほしくないというか。

参考資料

https://doc.powerdns.com/3/httpapi/README/#powerdns-api

https://doc.powerdns.com/3/authoritative/installation/

http://www.slideshare.net/mzdakr/powerdns

シェルの組込関数(ビルトイン)の使い方manを見る方法

Shell Built'in Functions のヘルプを見たい

Man ページだと見れないんだよ。man だと。

man history  ## 見れない。

man で見ると、shell builtins に飛ばされる。そしてオプションを見られない。

help を使う。

 help history

help コマンドを使う。

シェル組み込み関数を見るには help を使う

help のhelp を見る

ヘルプの使い方をとりえず見てみるのがいいですね man man するのと同じ感覚です。

takuya@~/Desktop$ help help
help: help [-dms] [pattern ...]
    組み込みコマンドの情報を表示します。

    組み込みコマンドに関する簡潔な要約を表示します。もし PATTERN が
    指定された場合は、PATTERN に一致する全てのコマンドに対する詳細な
    ヘルプを表示します。それ以外はヘルプトピックを表示します。

    オプション:
      -d    各ヘルプトピックに対して短い説明を出力します
      -m    使用法を擬似的な man ページ形式で表示します
      -s    一致した各トピックに対して簡単な使用法のみを表示します
        PATTERN

    引数:
      PATTERN   ヘルプトピックを指定するパターン

    終了ステータス:
    PATTERN が見つからないか無効なオプションが与えられない限り成功を返します。

history の使い方を見てみる。

history コマンドって使わない日が無いですよね。history -a なんて、bashrc に書いてて秒間ですげー数が実行されているし。

history: history [-c] [-d offset] [n] または history -anrw [filename] または history -ps arg [arg...]
    ヒストリ一覧を表示または操作します。

    行番号をつけてヒストリを表示します。操作した各項目には前に`*'が付きます。
    引数 N がある場合は最後の N 個の項目のみを表示します。

    オプション:
      -c    ヒストリ一覧から全ての項目を削除します。
      -d offset OFFSET 番目のヒストリ項目を削除します。

      -a    このセッションからヒストリファイルに行を追加します
      -n    ヒストリファイルからまだ読み込まれていない行を全て読み込みます
      -r    ヒストリファイルを読み込み、内容をヒストリ一覧に追加します
      -w    現在のヒストリをヒストリファイルに書き込みます。そしてそれらを
        ヒストリ一覧に追加します

      -p    各 ARG に対してヒストリ展開を実行し、結果をヒストリ一覧に追加し
        しないで表示します
      -s    ARG を単一の項目としてヒストリ一覧に追加します

    FILENAME を与えた場合、FILENAME がヒストリファイルをして使用されます。それが
    無く、$HISTFILE に値がある場合その値が使用されます。そうでなければ
    ~/.bash_history が使用されます。

    もし $HISTTIMEFORMAT 変数が設定され、NULL で無ければ、strftime(3) の書式
    文字列として各ヒストリ項目の時刻を表示する際に使用されます。それ以外は
    時刻は表示されません。

    終了ステータス:
    無効なオプションが与えられるかエラーが発生しない限り成功を返します。

history コマンドの使い方がわかりますね。

if / else の使い方も見れる

help if
if: if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi
    条件に従ってコマンドを実行します。

    `if COMMANDS' を実行します。この終了ステータスが 0 の場合、`then COMMANDS'
    を実行します。そうでない場合は、各 `elif COMMANDS' を順番に実行し、その
    終了ステータスが 0 の場合に、関連した `then COMMANDS' を実行し、if 文が
    完了します。それ以外の場合、 `else COMMANDS' が存在する場合には実行され
    ます。文全体の終了ステータスは、最後に実行したコマンドの終了ステータスか、
    または、テストした条件に true となるものが無い場合は 0 です。

    終了ステータス:
    最後に実行したコマンドの終了ステータスを返します。

シェルの関数や機能を見るにはhelp

man ではなくて、help を使います。

参考資料

http://unix.stackexchange.com/questions/18087/can-i-get-individual-man-pages-for-the-bash-builtin-commands

Mission Control :この遅すぎる機能をなんとかしたい

ミッションコントロールの切替が遅い

ミッションコントロール、遅くないですか。とくにWindow一覧。遅いんですよ思考が止まる

WindowsのAlt+Tabの機敏な動きが本当に懐かしい。

というわけで、調べてたら出てきた

defaults write com.apple.dock expose-animation-duration -float 0.05; killall Dock

これで、トラックパッドを上にしたにスライドした時の動き、また、F3をおした時の動きがキビキビしてて快適ですね。

元に戻すには

defaults delete com.apple.dock expose-animation-duration; killall Dock

ただ一度設定して慣れてしまうと、もう二度と元に戻れない体になると思います。

参考資料

http://www.makeuseof.com/tag/use-multiple-desktops-mac-os-x/

URLに含まれる数字のIDを隠したい時にhashid を使うと楽

Id丸見えっていろいろヤバイですよね。

とくに連番だと、連番のインクリメンツだと、つい出来心で連番を踏んでみたくなりますよね。

あと、マナー悪いクローラーがババっと来そう。

IDを隠す

IDを隠すにはmd5crc / sha で hexdigest すりゃイイんだけど、文字数が多すぎて見栄えが悪い。

URL 短縮系のサイトでやってる bitlyや google shorten と同じようなことが出来ないか考えてみたけど。

ちょっとアルゴリズムが思いつかなかったので、ライブラリを探してみました。

HashID で 数字のIDを隠す

hashids.org

数字を「配列」にすると、アルファベットでエンコードしてくれます。

各種言語で書かれているのでいいですね。

BASE64 だと辛いし BASE58 くらいでいいんですけどね。

BaseXX で文字を符号化する感じですね。Saltが使えるので便利です。

サンプル

hashids = Hashids.new "this is my salt"
id = 123
id = id.to_s
id = id.split //
id = id.map{|e| e.to_i }
id = hashids.encode(*id) ## ここで連番の数字を配列にしたものを渡す。
numbers = hashids.decode(id)

楽しいですね。

アルファベットだけでIDドコまで行けるか

6桁もアレば十分ですね

(26*2)6 =19,770,609,664

余裕見ても8桁ですかね。

php imagick でページ指定を簡略化して pdf を高速に処理する

ruby で出来たので、php でもできるかなと思って調べてみたら。

<?php
<?php 
$imagick = new Imagick(); 
$imagick->readImage('myfile.pdf[0]'); 
$imagick = $imagick->flattenImages(); 
$imagick->writeImage('pageone.jpg');
?> 

php のマニュアルにバッチリなコードが書いてあった。

でも動かすの大変だった。

php-magick で pdf を処理するには gsが必要なんだが、gs が入っててもコマンドラインオプションがあわなくて起動しなくて、解決方法を探してる間に時間が過ぎてしまった。

apt で入れた php-magick ではpdf が扱えない。

モジュールの依存関係、とくにphp はちょっとめんどくさいのでpecl 経由入れて解決させるしかないと思うけど、apt で使えないのは不便極まりないな。。。

エラー

PHP Fatal error:  Uncaught exception 'ImagickException' with message 'FailedToExecuteCommand `"gs" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 "-sDEVICE=pngalpha" -dTextAlphaBits=4 -dGraphicsAlphaBits=4 "-r72x72"  "-sOutputFile=/tmp/magick-31919s74grPtp69Oe%d" "-f/tmp/magick-31919cbojU1OZVN2V" "-f/tmp/magick-31919lAaYk4BJvvgD"' (-1) @ error/delegate.c/ExternalDelegateCommand/461' in /home/takuya/test.php:7
Stack trace:
#0 /home/takuya/test.php(7): Imagick->readimage('out.pdf')
#1 {main}
  thrown in /home/takuya/test.php on line 7

2016-11-10

debianphp のバージョンアップをしたので無事動かすことが出来た。