2013年4月29日月曜日

[C言語]semaphore

複数のスレッドを生成した場合に semaphore を使用して動作の順番を制御する。
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>

#define USE_SEMAPHORE 1
sem_t sem;

void *thread_func(void *param)
{
 int pid;
 int i;
 pthread_t thread_id;

#if USE_SEMAPHORE
 sem_wait(&sem);
#endif
 thread_id = pthread_self();
 printf("%s called\n", __FUNCTION__);
 printf("  thread ID = %ld\n", thread_id);
 printf("  2:pid = %d\n", pid);
 pid = getpid();
 sleep(5);
 printf("  done\n");
#if USE_SEMAPHORE
 sem_post(&sem);
#endif
}

#define THREAD_NUM_MAX 3
int main(void)
{
 pthread_t t[THREAD_NUM_MAX];
 int pid;
 int i;

#if USE_SEMAPHORE
 sem_init(&sem, 0, 1);
#endif

 pid = getpid();
 printf("1:pid = %d\n", pid);
 for (i = 0; i < THREAD_NUM_MAX; i++) {
  if (pthread_create(&t[i], NULL, thread_func, NULL) != 0) {
   printf("Failed pthread_create()\n");
   return -1;
  }
  printf("Next line of pthread_create() called. thead ID[%d] = %ld\n", i, t[i]);
 }

 for (i = 0; i < THREAD_NUM_MAX; i++) {
  pthread_join(t[i], NULL);
 }

#if USE_SEMAPHORE
 sem_destroy(&sem);
#endif

 printf("End of the program\n");

 return 0;
}
USE_SEMAPHORE を 0 にして semaphore を使用しなかった場合の出力結果
1:pid = 920
Next line of pthread_create() called. thead ID[0] = 7078224
thread_func called
  thread ID = 7078224
  2:pid = 7078224
thread_func called
Next line of pthread_create() called. thead ID[1] = 7078408
  thread ID = 7078408
  2:pid = 7078408
thread_func called
  thread ID = 7078544
  2:pid = 7078544
Next line of pthread_create() called. thead ID[2] = 7078544
  done
  done
  done
End of the program
3 つの子スレッドが同時に動作しているので全て sleep(5) を完了させて同時に終わる。
よって time コマンドでプログラムの実行時間を計測すると以下のように約 5 秒で終了している。
real    0m5.156s
user    0m0.405s
sys     0m0.015s
USE_SEMAPHORE を 1 にして semaphore を使用した場合の出力結果
1:pid = 1212
Next line of pthread_create() called. thead ID[0] = 7078256
thread_func called
  thread ID = 7078256
  2:pid = 7078256
Next line of pthread_create() called. thead ID[1] = 7078440
Next line of pthread_create() called. thead ID[2] = 7078576
  done
thread_func called
  thread ID = 7078440
  2:pid = 7078440
  done
thread_func called
  thread ID = 7078576
  2:pid = 7078576
  done
End of the program
1 つの semaphore を順番に取得 (wait/post) して動作しているので、3 つの子スレッドが順番に動作している。
time コマンドで実行時間を計測すると以下のように約 15 秒かかる。
real    0m15.203s
user    0m0.155s
sys     0m0.015s

[C言語]pthread

thread プログラム
#include <stdio.h>
#include <pthread.h>

void *thread_func(void *param)
{
 int pid;
 int i;
 pthread_t thread_id;

 thread_id = pthread_self();
 printf("%s called\n", __FUNCTION__);
 printf("  thread ID = %ld\n", thread_id);
 printf("  2:pid = %d\n", pid);
 pid = getpid();
 sleep(5);
 printf("  done\n");
}

int main(void)
{
 pthread_t thread;
 int pid;

 pid = getpid();
 printf("1:pid = %d\n", pid);
 if (pthread_create(&thread, NULL, thread_func, NULL) != 0) {
  printf("Failed pthread_create()\n");
  return -1;
 }
 printf("Next line of pthread_create() called. thead ID = %ld\n", thread);
 pthread_join(thread, NULL);

 printf("End of the program\n");

 return 0;
}
出力結果
1:pid = 4780
Next line of pthread_create() called. thead ID = 7078224
thread_func called
  thread ID = 7078224
  2:pid = 7078224
  done
End of the program
main() 関数から pthread_create() により thread_func が別スレッドとして生成される。
親スレッドは pthread_join() で子スレッドが終了してくるのを待つ。

[C言語]Queue

C での queue の使い方 (sys/queue.h)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/queue.h>

struct entry {
 int id;
 TAILQ_ENTRY(entry) entries;
};

int main(void)
{
 int i;
 struct entry *t, *p;
 TAILQ_HEAD(tailhead, entry) head;
 struct tailhead *headp;
 TAILQ_INIT(&head);

 for (i = 0; i < 10; i++) {
  t = (struct entry*)malloc(sizeof(struct entry));
  memset(t, 0, sizeof(t));
  t->id = i;
  TAILQ_INSERT_TAIL(&head, t, entries);
 }

 for (p = head.tqh_first; p != NULL; p = p->entries.tqe_next) {
  printf("%08x %d\n", p, p->id);
 }

 t = (struct entry*)malloc(sizeof(struct entry));
 memset(t, 0, sizeof(t));
 t->id = 100;

 printf("Push new entry after 4th element\n");
 p = head.tqh_first;
 for (i = 0; i < 3; i++) {
  p = p->entries.tqe_next;
 }
 TAILQ_INSERT_AFTER(&head, p, t, entries);

 for (p = head.tqh_first; p != NULL; p = p->entries.tqe_next) {
  printf("%08x %d\n", p, p->id);
 }

 printf("Pop head entry\n");
 TAILQ_REMOVE(&head, head.tqh_first, entries);

 for (p = head.tqh_first; p != NULL; p = p->entries.tqe_next) {
  printf("%08x %d\n", p, p->id);
 }

 return 0;
}
実行結果
>queue.exe
006b2580 0
006b2590 1
006b25a0 2
006b25b0 3
006b25c0 4
006b25d0 5
006b25e0 6
006b25f0 7
006b2600 8
006b2610 9
Push new entry after 4th element
006b2580 0
006b2590 1
006b25a0 2
006b25b0 3
006c2628 100
006b25c0 4
006b25d0 5
006b25e0 6
006b25f0 7
006b2600 8
006b2610 9
Pop head entry
006b2590 1
006b25a0 2
006b25b0 3
006c2628 100
006b25c0 4
006b25d0 5
006b25e0 6
006b25f0 7
006b2600 8
006b2610 9

C++ での queue class の使い方 (queue)
#include <iostream>
#include <queue>
using namespace std;

int main(void)
{
 int i;
 queue<int> que;

 for (i = 0; i < 10; i++) {
  que.push(i);
 }

 cout << "size=" << que.size() << endl;

 while (!que.empty()) {
  cout << que.front() << " ";
  que.pop();
 }
 cout << endl;

 return 0;
}
実行結果
>queue2.exe
size=10
0 1 2 3 4 5 6 7 8 9

[SELinux]SELinux を無効にする

テスト環境で Linux を使用している場合、SELinux がブロックすることで通信できないことが多々ある。テストで使用しているだけなので SELinux をとりあえず無効にしておく。
Example: /etc/selinux/config
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#       enforcing - SELinux security policy is enforced.
#       permissive - SELinux prints warnings instead of enforcing.
#       disabled - SELinux is fully disabled.
SELINUX=enforcing
# SELINUXTYPE= type of policy in use. Possible values are:
#       targeted - Only targeted network daemons are protected.
#       strict - Full SELinux protection.
SELINUXTYPE=targeted
SELINUX=enforcing を SELINUX=disabled とすることで無効になる。

[SELinux]セキュリティ・レベル

セキュリティ・レベルを調整する時は boolean パラメータを変更する。
例えば httpd の CGI 実行可否を設定しているパラメータは httpd_enable_cgi である。
# getsebool httpd_enable_cgi
httpd_enable_cgi --> on
# setsebool httpd_enable_cgi 0
# getsebool httpd_enable_cgi
httpd_enable_cgi --> off
httpd_enable_cgi を禁止すると /var/log/audit/audit.log に CGI 実行できなかったことが保存される。
type=AVC msg=audit(1289629357.378:26529): avc:  denied  { getattr } for  pid=1640 comm="httpd" path="/var/www/cgi-bin/python/test00.cgi" dev=dm-0 ino=22608 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:httpd_sys_script_exec_t:s0 tclass=file
boolean パラメータ一覧は getsebool -a で表示できる。
[root@fedora ~]# getsebool -a
abrt_anon_write --> off
allow_console_login --> off
allow_cvs_read_shadow --> off
allow_daemons_dump_core --> on
allow_daemons_use_tty --> off
allow_domain_fd_use --> on
allow_execheap --> off
allow_execmem --> on
allow_execmod --> off
allow_execstack --> on
(以下略)

[SELinux]起動時の設定

起動時の設定は /etc/selinux/config に記述してある。
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - SELinux is fully disabled.
SELINUX=enforcing
# SELINUXTYPE= type of policy in use. Possible values are:
# targeted - Only targeted network daemons are protected.
# strict - Full SELinux protection.
SELINUXTYPE=targeted

[SELinux]動作状態

動作状態は sestatus コマンドでも確認できる。
# sestatus
SELinux status:                 enabled
SELinuxfs mount:                /selinux
Current mode:                   enforcing
Mode from config file:          enforcing
Policy version:                 24
Policy from config file:        targeted

[SELinux]動作モード

モード確認
動作モードを確認するには getenforce コマンドを使用する。
# getenforce
Enforcing
Enforcingポリシーに違反するアクセスはログに書き出して "拒否" する。
Permissiveポリシーに違反するアクセスはログに書き出して "許可" する。

モード変更
動作モードの変更は setenforce コマンドを使用する。
# setenforce 0
# getenforce
Permissive
# setenforce 1
# getenforce
Enforcing

[SELinux]セキュリティ・コンテキスト

ファイルのセキュリティ・コンテキスト
ファイルのセキュリティ・コンテキストは ls -Z で確認できる。
"User" : "Role" : "Type or Domain" の順に表示される
# ls -Z
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 html
この html ディレクトリには system_u:object_r:httpd_sys_content_t というセキュリティコンテキストが付いている。User 識別子:Role 識別子:Type 識別子の順に並んでいる。
User 識別子Linux システム上のユーザー (uid) との紐付けはシステムへのログイン時に行われる。
Role 識別子RBAC (Role Based Access Control) で使用する root 権限の最小化で効果を発揮する。
Type 識別子, Domain 識別子すべてのアクセス制御はこの Type 識別子の組み合わせがセキュリティポリシーで定義されているかに基づいて決定される。

プロセスのセキュリティ・コンテキスト
プロセスのセキュリティ・コンテキストは ps -eZ で確認できる。
# ps -eZ
LABEL                                                 PID TTY       TIME     CMD
system_u:system_r:httpd_t:s0                          1594 ?        00:00:00 httpd
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 2450 ?        00:00:02 emacs
httpd の Domain 識別子は httpd_t となっている。emacs には unconfined_t が割り当てられている。
ログイン・ユーザーが起動したプログラムは unconfined_t で動作する。これにより SELinux の制限を受けなくなる。
  1. httpd が Web ページを読み込む前に SELinux モジュールに読み込み要求を伝える。
  2. SELinux モジュールは要求されたアクセスが許可されているか、「ポリシー・ファイル」を参照してセキュリティ・チェックをする。
  3. アクセスが許可された場合は httpd がアクセスを行う。アクセスが拒否された場合はアクセス拒否されたことがログに記録される。

[SELinux]用語

(Type-Enforcement)アクセス制御機能。ファイルなどのリソースにアクセスする時は TE によるチェックが入る。
ドメインすべてのプロセス (httpd など) に付与されるラベル。httpd の場合は httpd_t というドメイン
タイプすべてのリソース (ファイルやポートなど) に付与されるラベル。/var/www/html 以下のファイルは httpd_sys_content_t とういラベル
ポリシーどのドメインがどのタイプにアクセスできるかを示したルール。
ポリシー・ファイルSELinux がアクセス可否を判断するためのポリシーが書かれたファイル。
セキュリティ・コンテキストSELinux がプロセス, リソースに付与しているラベル。 リソースに対しては User 識別子, Role 識別子, Type 識別子を組み合わせたものになっている。プロセスに対しては User 識別子, Role 識別子, Domain 識別子を組み合わせたものになっている。

2013年4月7日日曜日

[ImageMagick]PDF から PNG ファイル作成

元画像 (test.pdf)

convert test.pdf test.png
出力結果 (test.png)

文字が汚いので xpdf を使って ppm ファイルに変換し、ppm ファイルを ImageMagick で png に変換する
pdftoppm.exe test.pdf test
test-000001.ppm が作成される
convert test-000001.ppm test-ppm.png
出力結果 (test-ppm.png)

test-ppm.png の画像サイズが 1240 x 1754 なので同サイズになるように ImageMagick のみで変換
convert test.pdf -resize 1754 test-resize.png
出力結果 (test-resize.png)

convert では白背景が透過になってしまうので、白背景を付けるようにする
convert test.pdf -alpha deactivate -resize 1754 test-resize-alpha.png
出力結果 (test-resize-alpha.png)

[Samba]ユーザー接続管理

ユーザーが接続している状態は smbstatus で確認できる。
# smbstatus

Samba version 3.5.6-69.fc13
PID     Username      Group         Machine
-------------------------------------------------------------------
2998    test          test          test-pc (::ffff:192.168.1.1)

Service      pid     machine       Connected at
-------------------------------------------------------
IPC$         2998    test-pc       Sat Dec 18 16:19:15 2010

No locked files
サーバーからユーザーの接続を切断する場合は smbcontrol を使う。
# smbcontrol 2998 close-share IPC$
# smbstatus

Samba version 3.5.6-69.fc13
PID     Username      Group         Machine
-------------------------------------------------------------------

Service      pid     machine       Connected at
-------------------------------------------------------

No locked files
第 1 引数は smbstatus で確認した pid, 第 2 引数は close-share, 第 3 引数は Service に出ている IPC$ を指定する。
Windows 側が接続状態を覚えている可能性があるのでコマンドプロンプトで確認する
C:\net use
切断する場合は
C:\net use /delete *

[Samba]Windows から接続できるよう共有フォルダを設定する

  1. /etc/samba/smb.conf
    1. サーバーオプション
      # ----------------------- Standalone Server Options ------------------------
          security = user
      ;    passdb backend = tdbsam
      Fedora13 の場合は passdb backend = tdbsam はコメントアウトしない
    2. 各ユーザの共有フォルダ設定
      #============================ Share Definitions ==============================
      
      [homes]
          comment = Home Directories
          browseable = no
          writable = yes
      ;    valid users = %S
      ;    valid users = MYDOMAIN\%S
    3. ログの出力先は次のように設定されている
      # --------------------------- Logging Options -----------------------------
          # logs split per machine
          log file = /var/log/samba/log.%m
          # max 50KB per log file, then rotate
          max log size = 50
  2. ユーザ追加
    # /usr/bin/smbpasswd -a username
    New SMB password:
    Retype new SMB password:
    Added user username
    /var/lib/samba/private/smbpasswd を見るとユーザが追加されていることが確認できる
  3. smb の再起動
    # /etc/init.d/smb restart
  4. Firewall 設定の変更
    Samba アクセスができるように Firewall の設定を変更する
  5. SELinux に接続を拒否されるので接続でできるように設定を変更する
    • 接続ブロックした時の Summery は以下の通り
      SELinux is preventing the samba daemon from reading users' home directories.
    • 設定変更は setseboool コマンドで行う
      # setsebool -P samba_enable_home_dirs=1
  6. Windows PC から接続して共有フォルダ (ユーザの home ディレクトリ) が見えることを確認する
  7. 起動時の Samba が動作するようにする
    # chkconfig --list smb
    smb                0:off    1:off    2:off    3:off    4:off    5:off    6:off
    # chkconfig smb on
    # chkconfig --list smb
    smb                0:off    1:off    2:on    3:on    4:on    5:on    6:off

[Samba]インストール

# yum install samba

[Devecot]ログ

ログ情報は /var/log/maillog に残される

[Devecot]インストール/起動

Dovecot は POP3, IMAP を扱う
  1. Dovecot のインストールをする
    # yum install dovecot
  2. 設定ファイルの /etc/dovecot.conf の確認
    • POP3 が使用できるように下記の設定を書き加える
      protocols = pop3
    • メール格納場所をユーザディレクトリ以下にする
      mail_location = maildir:~/Mail
  3. Linux 起動時に dovecot が起動できるようにする
    # chkconfig --list dovecot
    dovecot 0:off 1:off 2:off 3:off 4:off 5:off 6:off
    # chkconfig dovecot on
    # chkconfig --list dovecot
    dovecot 0:off 1:off 2:on 3:on 4:on 5:on 6:off
  4. dovecot を起動する
    # /etc/init.d/dovecot start
  5. 外部からアクセスできるように 110 (POP) が通るように Firewall を設定する

[Sendmail]Sendmail ログイン時のログ

  • SMTP 認証あり (保護された認証を使用する: ON)
    Nov 15 12:52:28 localhost sendmail[22189]: AUTH=server, relay=localhost [192.168.153.2] (may be forged), authid=test, mech=CRAM-MD5, bits=0
    Nov 15 12:52:28 localhost sendmail[22189]: oAF3qSbb022189: from=<test@local.local>, size=379, class="0", nrcpts=1, msgid=<4CE0AE69.4020102@local.local>, proto=ESMTP, daemon=MTA, relay=localhost [192.168.153.2] (may be forged)
    Nov 15 12:52:29 localhost sendmail[22190]: oAF3qSbb022189: to=<test@local.local>, ctladdr=<test@local.local> (500/500), delay=00:00:01, xdelay=00:00:01, mailer=local, pri=30640, dsn=2.0.0, stat=Sent
  • 認証あり (保護された認証を使用する: OFF)
    Nov 15 12:53:13 localhost sendmail[22195]: AUTH=server, relay=localhost [192.168.153.2] (may be forged), authid=test, mech=PLAIN, bits=0
    Nov 15 12:53:13 localhost sendmail[22195]: oAF3rDip022195: from=<test@local.local>, size=394, class="0", nrcpts=1, msgid=<4CE0AE97.2090307@local.local>, proto=ESMTP, daemon=MTA, relay=localhost [192.168.153.2] (may be forged)
    Nov 15 12:53:14 localhost sendmail[22196]: oAF3rDip022195: to=<test0@localhost>, ctladdr=<test@local.local> (500/500), delay=00:00:01, xdelay=00:00:01, mailer=local, pri=30654, dsn=2.0.0, stat=Sent
  • 認証なし
    Nov 17 09:04:48 localhost sendmail[2196]: oAH04mna002196: from=<test@local.local>, size=379, class="0", nrcpts=1, msgid=<4CE31C0E.4040301@local.local>, proto=ESMTP, daemon=MTA, relay=localhost [192.168.153.2] (may be forged)
    Nov 17 09:04:48 localhost sendmail[2197]: oAH04mna002196: to=<test@local.local>, ctladdr=<test@local.local> (500/500), delay=00:00:00, xdelay=00:00:00, mailer=local, pri=30616, dsn=2.0.0, stat=Sent
  • 認証失敗
    Nov 15 12:58:34 localhost sendmail[22223]: oAF3wXum022223: localhost [192.168.153.2] (may be forged) did not issue MAIL/EXPN/VRFY/ETRN during connection to MTA

[Sendmail]ログ

  • procmail: 各ユーザディレクトリの procmail.log に残される
  • Sendmail: /var/log/maillog に残される

[Sendmail]リレーを許可する

/etc/mail/access ファイルでリレーを許可する IP アドレスを指定する。192.168.0.0/24 を許可する場合は下記のように追記する。
Connect:localhost.localdomain   RELAY
Connect:localhost               RELAY
Connect:127.0.0.1               RELAY
Connect:192.168.0               RELAY
access.db ファイルを作成する
# makemap -v hash /etc/mail/access.db < /etc/mail/access

[Sendmail]新規ユーザ追加時の Mail ディレクトリ作成

/etc/skel 以下に Mail ディレクトリを作成しておく
# cd /etc/skel
# mkdir Mail
# mkdir Mail/cur
# mkdir Mail/new
# mkdir Mail/tmp
# chmod 700 -R Mail

[Sendmail]Procmail 設定

sendmail は Maildir 形式メールボックスへ配送できないので、Procmail の設定をする

/etc/procmailrc を作成
SHELL=/bin/bash
PATH=/usr/bin:/bin
DROPPRIVS=yes
MAILDIR=$HOME/Mail
DEFAULT=$MAILDIR/
LOGFILE=$HOME/procmail.log

[Sendmail]SMTP 認証 (SMTP Auth.)

  1. sendail.mc を編集する
    • 以下の箇所の行頭に dnl を付けて外部からアクセスできるようにする
      編集前
      DAEMON_OPTIONS(`Port=smtp,Addr=127.0.0.1, Name=MTA')dnl
      編集後
      dnl DAEMON_OPTIONS(`Port=smtp,Addr=127.0.0.1, Name=MTA')dnl
    • 以下の箇所の行頭にある dnl を削除し SMTP 認証を使うようにする
      編集前
      dnl TRUST_AUTH_MECH(`EXTERNAL DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')dnl
      dnl define(`confAUTH_MECHANISMS', `EXTERNAL GSSAPI DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')
      編集後
      TRUST_AUTH_MECH(`EXTERNAL DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')dnl
      define(`confAUTH_MECHANISMS', `EXTERNAL GSSAPI DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')
  2. sendmail.cf 作成
    /etc/mail にある make を実行して sendmail.cf を作成する
    # make
  3. パスワード設定
    # sasldblistusers2
    test@localhost.localdomain: userPassword
  4. sendmail を再起動する
    # /etc/init.d/sendmail restart
  5. SMTP 認証用サービス saslauthd を起動する
    # /etc/init.d/saslauthd start
  6. saslauthd が Linux 起動時に起動するように設定する
    # chkconfig saslauthd on

[Sendmail]check_mail のテスト

# sendmail -bt -C sendmail.cf

[Sendmail]外部メールクライアントからのテスト

メールクライアントの設定
メールアドレスuser@サーバの IP address
POP サーバサーバの IP address
POP ユーザ名user
POP port110
SMTP サーバサーバの IP address
SMTP ユーザ名user
SMTP port25
  1. Sendmail が "user@サーバの IP address" というメールアドレスから受信できるように設定する
    1. /etc/mail/local-host-names に以下を追加
      サーバの IP address
    本来はサーバのドメイン名を決めてそれをここに記述するのだが、今回は IP address を直接記載にする
  2. 外部からアクセスできるように Firewall の設定で 25 (SMTP) を許可する
  3. Sendmail を再起動
    # /etc/init.d/sendmail restart
  4. 外部メールクライアントからメールの送受信ができるか確認する
  5. メールが送信されると /home/user/Mail/new にメールが格納される
  6. メールを受信すると /home/user/Mail/cur に受信済みメールが格納される (メールクライアントの設定で「サーバにメールを残さない」にしておくとここには格納されずに削除される)

[Sendmail]動作確認

  1. mail コマンドで送信
    $ mail user@localhost
    Subject: Test mail
    This is test mail.
    .         ← サイドにピリオドを押して終了
    EOT
  2. 受信確認
    $ cat /var/mail/user
    From user@localhost.localdomain Sun Nov 29 01:59:31 2009
    Return-Path: <user@localhost.localdomain>
    
    (中略)
    
    To: user@localhost.localdomain
    Subject: Test mail
    User-Agent: Heirloom mailx 12.4 7/29/08
    MIME-Version: 1.0
    Content-Type: text/plain; charset=us-ascii
    Content-Transfer-Encoding: 7bit
    
    This is test mail.

2013年4月6日土曜日

[Sendmail]Sendmail 起動

Sendmail はメールの転送を行う SMTP を扱う
  1. chkconfig で sendmail が起動するようになっているか確認する
    # chkconfig --list sendmail
    mail       0:off   1:off   2:on    3:on    4:on    5:on    6:off
  2. 設定ファイル /etc/mail/sendmail.mc から /etc/mail/sendmail.cf を作成できるように sendmail-cf をインストールする
    # yum install sendmail-cf

[PHP][PHPExcel]Cellに属性を付ける

Cellに「折り返して全体を表示」「文字の配置 - 縦位置 = 上詰め」属性を付ける
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>PHP Excel</title>
  </head>
  <body>
<?php
require_once '../PHPExcel_1.7.8/Classes/PHPExcel.php';

// Create new PHPExcel object
printWithTime('Create new PHPExcel object<br/>');
$objPHPExcel = new PHPExcel();
$sheet = $objPHPExcel->setActiveSheetIndex(0);

// フォント
printWithTime('Set default font<br/>');
$sheet->getDefaultStyle()->getFont()->setName('メイリオ');

// cell に「折り返して全体を表示 (Wrap text)」 属性を付ける
$sheet->getDefaultStyle()->getAlignment()->setWrapText(true);

// cell に「文字の配置 - 縦位置 = 上詰め (vertical = top)」属性を付ける
$sheet->getDefaultStyle()->getAlignment()->setVertical('top');

// Add data
printWithTime('Add data<br/>');
$str = "Hello, world.\nThis is a pen.\nGood bye.";
$sheet->setCellValue('A1', 1);
$sheet->setCellValue('B1', $str);

// Save Excel5 file
$outputFilename = 'php_excel3_output.xls';
printWithTime('Write to Excel5 format<br/>');
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
$objWriter->save($outputFilename);
printWithTime('File written to Excel5 format<br/>');

print "<br/><br/>";
print "Copy $outputFilename to your local PC and open it!<br/>";

/***********************************************************************
 * 時刻と一緒にデバッグ文表示
 ***********************************************************************/
function printWithTime($str)
{
    print "[" . date('H:i:s') . "] " . $str;
}

?>
  </body>
</html>

[PHP][PHPExcel]配列からExcelにデータを書き出す

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>PHP Excel</title>
  </head>
  <body>
<?php
require_once '../PHPExcel_1.7.8/Classes/PHPExcel.php';

// Create new PHPExcel object
printWithTime('Create new PHPExcel object<br/>');
$objPHPExcel = new PHPExcel();

// フォント
printWithTime('Set default font<br/>');
$objPHPExcel->setActiveSheetIndex(0)->getDefaultStyle()->getFont()->setName('メイリオ');

// 配列でデータを準備
$data = array(
    array(1, 'Dog', 'Tokyo', '犬'),
    array(2, 'Cat', 'Chiba', '猫'),
    array(3, 'Bird', 'Saitama', '鳥')
    );

var_dump($data);
print "<br/>";

// Add data
printWithTime('Add data<br/>');
$rowNum = 1;
foreach ($data as $row) {
    $colNum = 0;
    foreach ($row as $d) {
        $objPHPExcel->setActiveSheetIndex(0)->setCellValueByColumnAndRow($colNum++, $rowNum, $d);
    }
    $rowNum++;
}

// Save Excel5 file
$outputFilename = 'php_excel2_output.xls';
printWithTime('Write to Excel5 format<br/>');
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
$objWriter->save($outputFilename);
printWithTime('File written to Excel5 format<br/>');

print "<br/><br/>";
print "Copy $outputFilename to your local PC and open it!<br/>";

/***********************************************************************
 * 時刻と一緒にデバッグ文表示
 ***********************************************************************/
function printWithTime($str)
{
    print "[" . date('H:i:s') . "] " . $str;
}

?>
  </body>
</html>

[PHP][PHPExcel]Excelファイルに書き出す

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>PHP Excel</title>
  </head>
  <body>
<?php
require_once '../PHPExcel_1.7.8/Classes/PHPExcel.php';

// Create new PHPExcel object
printWithTime('Create new PHPExcel object<br/>');
$objPHPExcel = new PHPExcel();

// Add some data
printWithTime('Add some data<br/>');
$objPHPExcel->setActiveSheetIndex(0)
            ->setCellValue('A1', 'Hello')
            ->setCellValue('B2', 'world!');

// Save Excel5 file
$outputFilename = 'php_excel_output.xls';
printWithTime('Write to Excel5 format<br/>');
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
$objWriter->save($outputFilename);
printWithTime('File written to Excel5 format<br/>');

print "<br/><br/>";
print "Copy $outputFilename to your local PC and open it!<br/>";

/***********************************************************************
 * 時刻と一緒にデバッグ文表示
 ***********************************************************************/
function printWithTime($str)
{
    print "[" . date('H:i:s') . "] " . $str;
}

?>
  </body>
</html>

[PHP][PHPExcel]インストール

  1. PHPExcel の Downloads から PHPExcel をダウンロードする
  2. ダウンロードしたファイルを解凍してサーバーに置く