それマグで!

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

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

phpで改行が反映されない件(終了タグと改行コードの関係)

php で改行コードが反映されないことがあります。

LFでもCRLFでも関係なく、文字コードも関係ありません。php では終了タグで「改行」すると、出力には改行が反映されません。

<?php 

$title = 'コーチングのプロが教える 「ほめる」技術';
$author = '鈴木 義幸';
?>

著者:<?= $title?>
書題:<?= $author?>

実行結果

$ php sample.php

著者:コーチングのプロが教える 「ほめる」技術書題:鈴木 義幸

不思議ですね。

次のように、単位が入るとさらに表示が想像がつかなくなります。

<?php 

$title = 'コーチングのプロが教える 「ほめる」技術';
$author = '鈴木 義幸';
$price = 1047;
?>
著者:<?= $title?>
価格:<?= $price;?>円
書題:<?= $author?>

これを実行すると次のようになります。

$ php sample.php
著者:コーチングのプロが教える 「ほめる」技術価格:1047円
書題:鈴木 義幸

”円”にだけ改行が反映されています。何故なんでしょうか。改行は無視されるときとされない時があるんです。

改行は反映されません。

php では、<?php ?> で囲まれたエリアはそのまま、コードとして解釈されます。と一般的に習うんでしょうけど、例外があります。

終了タグは、「改行」を含んで終了と解釈されます。?> ⏎?> と同じなのです。

改行コードは2つ続いても、一つになる。

一つだけだと

abc<?php
?>

実行後は

abc

になります。

なので、改行を反映したいときは、空行を入れるか、空白を入れます。

abc<?php
?> ⏎
⏎

これが実行されると

abc⏎

になります。

対策

こうします。空白を入れます。

<?php echo $name; ?>␣⏎

便利なときもある。

php のファイルから php をrequire したときに、改行コードをいい感じにしてくれるので便利なこともある。

テンプレートのフォーマットでは空白か空行を多めにいれる。

そういう仕様なのです。如何ともし難い。仕方ないのです。php で改行がでなくてもHTMLは改行を無視するのであまり気になっていないという現実があります。

これが、phpCSVバッチ処理やメール送信など、プレーンテキストを扱うと途端に問題になります。とくにCSVとメールでしょうか。

php の仕様

仕様なのです。phpは4→5, 5→6とかなり後方互換を切り捨ててきたので、そろそろこの辺もバッサリ切ってほしいと思ったりするのですが。

テンプレートとしてphpを実行したときに改行コードを意識する必要があるのは若干不便ではないでしょうか。

実験に使用したphp

今回は、このphp でサンプルコードを書いて実行しています。

PHP 7.3.11 (cli) (built: Oct 24 2019 11:29:42) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.11, Copyright (c) 1998-2018 Zend Technologies
    with Xdebug v2.7.2, Copyright (c) 2002-2019, by Derick Rethans

参考資料

mac で sendmail コマンドを動かす。

sendmailgmailSMTPを使う。

mac には 最初から postfix が入っているので、 postfix を使うのが手っ取り早い

postfix を使ってSMTPリレーをし、GmailSMTPサーバーに接続する。

sasl password ファイルを用意する

takuya@mail$ sudo -e  /etc/postfix/sasl_passwd

/etc/postfix/sasl_passwd

smtp.gmail.com:587 youname@gmail.com:your_password

main.cf の作成

私の環境では、なぜか、main.cf が空っぽのファイルになっていたので、デフォルトを取り出します。

sudo cp  /etc/postfix/main.cf~orig /etc/postfix/main.cf

postmap の実行

postmap をつかって、パスワードをdb に登録します。

sudo postmap /etc/postfix/sasl_passwd

main.cf でリレーを設定します。

main.cf を開いて、末尾に追記します。

# Apple Defaults
#
message_size_limit = 10485760
mailbox_size_limit = 0
biff = no
mynetworks = 127.0.0.0/8, [::1]/128
smtpd_client_restrictions = permit_mynetworks permit_sasl_authenticated permit
recipient_delimiter = +
tls_random_source = dev:/dev/urandom
smtpd_tls_ciphers = medium
#### ここから追記
## gmail へのリレー設定

relayhost=smtp.gmail.com:587
smtp_sasl_auth_enable=yes
smtp_sasl_password_maps=hash:/etc/postfix/sasl_passwd
smtp_use_tls=yes
smtp_tls_security_level=encrypt
tls_random_source=dev:/dev/urandom
smtp_sasl_security_options = noanonymous
smtp_always_send_ehlo = yes
smtp_sasl_mechanism_filter = plain

postfix の実行

設定ができたので、postfixを起動します。

sudo postfix start

起動を確認しておきます。

takuya@mail$ ps aux | grep postfix
321:_postfix          9807   0.0  0.0  4305160   4004   ??  S     4:32AM   0:00.03 tlsmgr -l -t unix -u
325:_postfix          9461   0.0  0.0  4324644   4092   ??  S     4:28AM   0:00.04 qmgr -l -t fifo -u
326:_postfix          9460   0.0  0.0  4332788   4036   ??  S     4:28AM   0:00.03 pickup -l -t fifo -u -o content_filter=
327:root              9459   0.0  0.0  4297908    560   ??  Ss    4:28AM   0:00.03 /usr/libexec/postfix/master -w

終了するときは、 

sudo postfix stop

sendmail コマンドでテストメールを送信します。

サンプル用のメールを作成します。 sample-mail.txt

To:takuya@example.com
Subject: HELLO , from test



Hi, can you see my mail?

sendmail コマンドで送信します。

cat sample-mail.txt | sendmail -i -t

メールの受信を確認します。

f:id:takuya_1st:20191213170612p:plain

無事に届けばOKです。

注意点

幾つか、気にしておく点をメモしておきます。

ポート開けっ放し?

postfix を常時動かすのはセキュリティ的に怖いのですが。使うときだけ起動できるので、それで妥協する。

sendmail コマンドとを互換性を持った別のコマンドを作ってもいいんですけど。作るのはめんどくさすぎるので

使うときのみ postfix を起動し使い終わったら終了するようにしておく。

また、smtp のリレーを localhost ( ::1 / 127.0.0.1 ) に限定するのも一つの手段です。

GmailSMTPを使うために

GmailSMTPは「安全性の低いアプリ」などと呼称されている 。安全性の低いアプリ( less secure apps ) をオンにしないとSMTP経由でメールが送れないかもしれない。

最近は、SMTPだけは開放されているようです。以前はこれをONにしないとSMTPが使えなかった。

指定するGoogleSMTP(s)のポートによっては使えない可能性が高い。

f:id:takuya_1st:20191213170602p:plain f:id:takuya_1st:20191213170608p:plain

lscpu コマンドが便利。 cat /proc/cpuinfo がメニーコアだと使いにくい

CPU マルチコア・マルチスレッド化 して情報を見にくい。

cat /proc/cpuinfo の出力が多すぎて見にくい。

表示は4コア2スレッドの合計8スレッドのCPUなんだけど、この数がどんどん増えていくんですよね。Ryzenとか買った日には、最大64個とかになるんでしょ?

proc/cpuinfo はもう限界。 lscpu を使う。

代替手段として lscpu コマンドを使うと便利。

takuya@:~$ LANG=C lscpu
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                8
On-line CPU(s) list:   0-7
Thread(s) per core:    2
Core(s) per socket:    4
Socket(s):             1
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 94
Model name:            Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz
Stepping:              3
CPU MHz:               799.987
CPU max MHz:           4000.0000
CPU min MHz:           800.0000
BogoMIPS:              6816.00
Virtualization:        VT-x
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              8192K
NUMA node0 CPU(s):     0-7
Flags:                 fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch invpcid_single ibrs ibpb stibp kaiser tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp

日本語表記もできる

takuya@:~$ lscpu
アーキテクチャ: x86_64
CPU 操作モード:   32-bit, 64-bit
バイト順序:       Little Endian
CPU:                   8
オンラインになっている CPU のリスト:0-7
コアあたりのスレッド数:2
ソケットあたりのコア数:4
ソケット数:       1
NUMA ノード数:     1
ベンダー ID:       GenuineIntel
CPU ファミリー:   6
モデル:             94
モデル名:          Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz
ステッピング:    3
CPU MHz:               799.987
CPU 最大 MHz:        4000.0000
CPU 最小 MHz:        800.0000
BogoMIPS:              6816.00
仮想化:             VT-x
L1d キャッシュ:   32K
L1i キャッシュ:   32K
L2 キャッシュ:    256K
L3 キャッシュ:    8192K
NUMA ノード 0 CPU:  0-7
フラグ:             fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch invpcid_single ibrs ibpb stibp kaiser tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp