揮発性のメモ2

http://d.hatena.ne.jp/iww/

apache2.4でCGIを動かすやつ

bashとかpythonとか普通じゃないやつで遊ぶ用


mod_cgid.so を有効にする
コマンドで有効化する(21世紀なので、シンボリックリンクを手で書いたりしない)

sudo a2enmod cgid

よくある設定

Alias "/hoge" "/home/unko/project/hoge"
<Directory "/home/unko/project/hoge">
    # 拡張子.cgi をCGIとみなす
    AddHandler cgi-script .cgi

    # このディレクトリで許すやつ
    Options ExecCGI FollowSymLinks Indexes
    # .htaccessで上書きを許すやつ
    AllowOverride Options AuthConfig FileInfo Limit Indexes

    # このディレクトリにアクセスできる人
    Require all granted
</Directory>
Options このディレクトリで許すやつ
ExecCGI .cgiの実行を許す
FollowSymLinks シンボリックリンクをたどるの許す
Indexes インデックス表示
AllowOverride .htaccessで設定の上書きを許すやつ
Options Options の上書きを許す
AuthConfig BASIC認証
FileInfo mod_rewrite
Limit IPアドレスでのアクセス制限とか用
Indexes インデックス表示

Require all granted

デフォルトではアクセスが無効になっているので、全ての人がアクセスできるようにする

うごかないとき

404
ディレクトリがほんとうにない
/を付けないとDocumentRootになるとか
403
Require all granted を書く
500
実行属性つける
ダウンロードされる
AddHandler cgi-script .cgi を書く
ソースがでる
mod_cgid.so を有効にする

core - Apache HTTP サーバ バージョン 2.4
Apache 2.4.2でCGIが動かない: ■メモ帳
mod_authz_core - Apache HTTP Server Version 2.4
Ubuntu ServerでCGIプログラムを動作させる - サーバーでもUbuntuを使っています
» bashでCGI (1) Apacheの設定 TECHSCORE BLOG
Apacheで動かすphp,python,ruby の Hello World まとめ - Incoming!

ブラウザで見ているPHPプログラムをデバッグする。

Debian 9.5 stretch
apache 2.4.25
PHP 7.0
XDEBUG 2.5

サーバ側準備

XDEBUGモジュールをインストール

apt install php-xdebug

XDEBUG設定ファイルを編集

; /etc/php/7.0/mods-available/xdebug.ini
; モジュールロード指定
zend_extension=xdebug.so

; リモートデバッグの有効化  0:無効, 1:有効
xdebug.remote_enable = 1
; サーバからクライアントに接続(2.1以降から使える)  0:無効, 1:有効
xdebug.remote_connect_back = 1

; 接続ポート番号
xdebug.remote_port = 9001
; デバッグ開始の合言葉
xdebug.idekey = "PHPSTORM"

クライアント側準備

ポート設定

Settings → Languages&Frameworks → PHP → Debug
Debug port を 9001 に編集

サーバ設定

Settings → Languages&Frameworks → PHP → Servers
+を押してサーバを追加する
(ローカルフォルダとリモートパスとの対応をちゃんと書くこと)

デバッグ設定

Add Coinfigurationを押して、プロジェクトごとのデバッグ設定を作成する

デバッグ設定は作成しなくても良いが、作成しておくと合言葉で接続制限をかけられるようになる。


XDEBUG固有の設定項目はここまでが最低限。

接続待ち受け開始

"Start Listening for PHP Debug Connections" を押してオンにし、接続可能状態にする。

デバッグしたくなくなったらオフにするとよい

ブラウザで接続

URLの末尾に ?XDEBUG_SESSION_START=PHPSTORM をつけてアクセスすると、デバッガが有効になる。
(※PHPSTORMは設定ファイルにも書いた合言葉)
一度有効になるとクッキーに残り、以降ずっと有効になる。
やめたくなったらXDEBUG_SESSION_STOPを指定

timespec の足し算引き算

#include <time.h>   // clock_gettime
#include <stdio.h>  // printf


struct timespec *timessub(const struct timespec *A, const struct timespec *B, struct timespec *C)
{
    C->tv_sec  = A->tv_sec  - B->tv_sec;
    C->tv_nsec = A->tv_nsec - B->tv_nsec;
    if(C->tv_nsec<0){
        C->tv_sec--;
        C->tv_nsec += 1000000000;
    }
    
    return C;
}
struct timespec *timesadd(const struct timespec *A, const struct timespec *B, struct timespec *C)
{
    C->tv_sec  = A->tv_sec  + B->tv_sec;
    C->tv_nsec = A->tv_nsec + B->tv_nsec;
    if(C->tv_nsec>=1000000000){
        C->tv_sec++;
        C->tv_nsec -= 1000000000;
    }
    
    return C;
}


int main()
{
    struct timespec A = { 3, 500000000 };
    struct timespec B = { 1, 600000000 };
    struct timespec C;

    timessub(&A,&B,&C);
    printf("tv_sec  = %ld\n", C.tv_sec);
    printf("tv_nsec = %ld\n", C.tv_nsec);

    timesadd(&A,&B,&C);
    printf("tv_sec  = %ld\n", C.tv_sec);
    printf("tv_nsec = %ld\n", C.tv_nsec);

    return 0;
}

flock

ファイルロックを使ったプロセス間での排他制御

// gcc -Wall -lpthread test_flock.c

#include <fcntl.h>      // O_CREAT
#include <sys/file.h>   // flock
#include <stdio.h>      // printf
#include <unistd.h>     // sleep

int main()
{
    int fd = open("/tmp/hoge", O_CREAT, 0600);

    printf("ロック\n");
    flock(fd,LOCK_EX);

    printf("30秒スリープ\n");
    sleep(30);
    
    printf("アンロック\n");
    flock(fd,LOCK_UN);
    
    return 0;
}

Man page of FLOCK

  • 長所
    • 実装が超簡単
    • プログラムが途中で死んでもロックが解除される
      • これは他のすべての問題を無視できる強み
    • 他言語との連携も簡単
    • 排他ロックだけじゃなく共有ロックもできる
    • 他プロセスとの待ち合わせが発生してもそんなに遅延しない
      • もともとが超遅いから競合の時間が目立たないだけかも
  • 短所
    • めちゃくちゃ遅い
      • sem_waitとかの40倍くらい遅い
      • ロックファイルをRAMディスク上に作ってもダメ

pthread_mutex_lock

Pスレッドのmutexを使ったプロセス間での排他制御

// gcc -Wall -lpthread test_mutex.c -lrt
// 動かんときは rm /dev/shm/hoge

#include <fcntl.h>      // O_CREAT
#include <stdio.h>      // printf
#include <unistd.h>     // sleep
#include <sys/mman.h>   // mmap
#include <stdlib.h>     // exit
#include <pthread.h>    // pthread

#define die(msg) do{ perror(msg); exit(EXIT_FAILURE); }while(0)

int main()
{
    pthread_mutex_t *mp;
    // まず共有メモリを普通にオープンし、
    int fd = shm_open("/hoge", O_RDWR, 0600);
    if(fd<0){
        // 共有メモリが無いときは新規に作成した上で
        fd = shm_open("/hoge", O_CREAT|O_EXCL|O_RDWR, 0600);
        if(fd<0) die("shm_open O_CREAT");
        // 初期化をおこなう
        ftruncate(fd, sizeof(pthread_mutex_t));
        mp = mmap(NULL, sizeof(pthread_mutex_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
        // mutexを作成、初期化
        pthread_mutexattr_t mattr;
        pthread_mutexattr_init(&mattr); // mutexの設定値を初期化
        pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED); // プロセス間有効に設定
        pthread_mutex_init(mp, &mattr); // mutex本体を初期化
    }else{
        // 共有メモリ上のmutexを参照する
        mp = mmap(NULL, sizeof(pthread_mutex_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    }

    printf("ロック\n");
    pthread_mutex_lock(mp);

    printf("30秒スリープ\n");
    sleep(30);
    
    printf("アンロック\n");
    pthread_mutex_unlock(mp);
    
    return 0;
}

Man page of PTHREAD_MUTEX

  • 長所
    • 結構速い
    • sem_waitよりもさらにちょっとだけ速い
      • 1割くらい速い感じ
      • プロセス間の待ち合わせが倍くらい速い気がする
  • 短所
    • 実装が超面倒くさい
      • 共有メモリを確保するのがだるい
      • mutexが初期化されてるかどうかも意識しないといけない
    • プログラムが途中で死ぬとロックがかかりっぱなしになる
    • 他言語と連携はできない

sem_init

共有メモリ上の名前なしセマフォを使ったプロセス間での排他制御

// gcc -Wall -lpthread test_seminit.c -lrt
// 動かんときは rm /dev/shm/hoge

#include <fcntl.h>      // O_CREAT
#include <semaphore.h>  // sem_wait
#include <stdio.h>      // printf
#include <unistd.h>     // sleep
#include <sys/mman.h>   // mmap
#include <stdlib.h>     // exit

#define die(msg) do{ perror(msg); exit(EXIT_FAILURE); }while(0)

int main()
{
    sem_t *sem;
    // まず共有メモリを普通にオープンし、
    int fd = shm_open("/hoge", O_RDWR, 0600);
    if(fd<0){
        // 共有メモリが無いときは新規に作成した上で
        fd = shm_open("/hoge", O_CREAT|O_EXCL|O_RDWR, 0600);
        if(fd<0) die("shm_open O_CREAT");
        // セマフォとして初期化をおこなう
        ftruncate(fd, sizeof(sem_t));
        sem = mmap(NULL, sizeof(sem_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
        // 1を指定するとバイナリセマフォになるよ
        sem_init(sem, 1, 1);
    }else{
        // 共有メモリ上のセマフォを参照する
        sem = mmap(NULL, sizeof(sem_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    }

    printf("ロック\n");
    sem_wait(sem);

    printf("30秒スリープ\n");
    sleep(30);
    
    printf("アンロック\n");
    sem_post(sem);
    
    return 0;
}

Man page of SEM_INIT

  • 長所
    • 結構速い
    • 実は普通のopenで普通のファイルでも動く
  • 短所
    • 共有メモリを確保するのがだるい
      • セマフォが初期化されてるかどうかも意識しないといけない
      • すでにある共有メモリに間借りするとかでない限り避けたい
    • プログラムが途中で死ぬとロックがかかりっぱなしになる
    • 他言語と連携はできない

sem_open

名前付きセマフォを使ったプロセス間での排他制御

// gcc -Wall -lpthread test_sem.c
// 動かんときは rm /dev/shm/sem.unko

#include <fcntl.h>      // O_CREAT
#include <semaphore.h>  // sem_wait
#include <stdio.h>      // printf
#include <unistd.h>     // sleep

int main()
{
    // 1を指定するとバイナリセマフォになるよ
    sem_t *sem = sem_open("/unko", O_CREAT, 0600, 1);

    printf("ロック\n");
    sem_wait(sem);

    printf("30秒スリープ\n");
    sleep(30);
    
    printf("アンロック\n");
    sem_post(sem);
    
    return 0;
}

Man page of SEM_OPEN

  • 長所
    • 実装が超簡単
    • 結構速い
  • 短所
    • プログラムが途中で死ぬとロックがかかりっぱなしになる
    • 他言語と連携はできない