TLDR;
我有一個shell腳本,從命令行運行時工作正常,但如果從PHP腳本中調用(通過Web訪問)則不行.
在這兩種情況下,主叫用戶都是www-data.
線路失敗是這樣的:
openssl genrsa -des3 -out certs/$PCODE.key -passout env:PASSPHRASE 2048
為什么會這樣?我該怎么調試呢?
全文
我有以下腳本,它是this gist的略微修改版本,用于生成自簽名SSL證書.
當我從終端運行它作為www-data時,它可以正常工作并生成密鑰文件,CSR和SSL證書文件.但是當我從PHP腳本中調用腳本時,它會輸出錯誤并且不會生成任何文件.是什么導致失敗?我該怎么調試呢?
從終端:
me@machine$sudo su www-data
www-data@machine$./gencert.sh acme
www-data will generate an SSL cert for acme.dev
Command after line 32 executed oK
Passphrase expoted as I7gOnWxWd0hOk38Zu ... FbxL3K3Rzlv
Generating RSA private key, 2048 bit long modulus
..............................................+++
.................+++
e is 65537 (0x10001)
Command after line 49 executed oK
Command after line 54 executed oK
Command after line 65 executed oK
writing RSA key
Command after line 69 executed oK
Signature ok
subject=/C=IR/ST=Alborz/.../emailAddress=noreply@acme.dev
Getting Private key
Command after line 74 executed oK
產生的文件:
> certs / acme.key.org
> certs / acme.key
> certs / acme.csr
> certs / acme.crt
來自PHP:
$r = `/var/www/testbench/pm/shell/gencert.sh acme`;
echo $r;
沒有生成文件,輸出如下:
www-data will generate an SSL cert for acme.dev
Command after line 32 executed oK
Passphrase expoted as 1Fd1seZoe2XF ... oSmQFJdVpdwOeTo2CK5VjLxp
Error. Return value = 1 after line 49
返回1的行是這樣的:
openssl genrsa -des3 -out certs / $PCODE.key -passout env:PASSPHRASE 2048
這是修改后的shell腳本:
#!/bin/bash
# Bash shell script for generating self-signed certs. Run this in a folder, as it
# generates a few files. Large portions of this script were taken from the
# following artcile:
#
# http://usrportage.de/archives/919-Batch-generating-SSL-certificates.html
# https://deliciousbrains.com/ssl-certificate-authority-for-local-https-development/
# Additional alterations by: Brad Landers
# Date: 2012-01-27
# Script accepts a single argument, the fqdn for the cert
PCODE="$1"
if [ -z "$PCODE" ]; then
echo "Usage: $(basename $0) "
exit 11
fi
THE_USER="$(whoami)"
echo "$THE_USER will generate an SSL cert for $PCODE.dev"
fail_if_error() {
[ $1 != 0 ] && {
echo -n "Error. Return value = $1 after line $LASTLINE"
unset PASSPHRASE
exit 10
}
echo "Command after line $LASTLINE executed oK"
}
# Generate a passphrase
LASTLINE="${LINENO}"
export PASSPHRASE=$(head -c 500 /dev/urandom | tr -dc a-z0-9A-Z | head -c 128; echo)
fail_if_error $?
echo -n "Passphrase expoted as "
printenv PASSPHRASE
# Certificate details; replace items in angle brackets with your own info
subj="
C=IR
ST=Alborz
O=ACME
localityName=Karaj
commonName=*.$PCODE.dev
organizationalUnitName=WebAdmin
emailAddress=noreply@$PCODE.dev
"
LASTLINE="${LINENO}"
# Generate the server private key
openssl genrsa -des3 -out certs/$PCODE.key -passout env:PASSPHRASE 2048
fail_if_error $?
LASTLINE="${LINENO}"
# Generate the CSR
openssl req \
-new \
-batch \
-subj "$(echo -n "$subj" | tr "\n" "/")" \
-key certs/$PCODE.key \
-out certs/$PCODE.csr \
-passin env:PASSPHRASE
fail_if_error $?
LASTLINE="${LINENO}"
cp certs/$PCODE.key certs/$PCODE.key.org
fail_if_error $?
LASTLINE="${LINENO}"
# Strip the password so we don't have to type it every time we restart Apache
openssl rsa -in certs/$PCODE.key.org -out certs/$PCODE.key -passin env:PASSPHRASE
fail_if_error $?
LASTLINE="${LINENO}"
# Generate the cert (good for 10 years)
openssl x509 -req -days 3650 -in certs/$PCODE.csr -signkey certs/$PCODE.key -out certs/$PCODE.crt
fail_if_error $?
解決方法:
要執行的命令具有相對路徑,例如:certs / $PCODE.key.當您執行命令時(在這種情況下通過反引號操作符),路徑相對于PHP進程的當前工作目錄進行擴展.這很少(如果有的話)與命令shell使用的路徑相同.
要調試這個,你可以使用strace擴展你的實際命令,例如:strace openssl ….這將為你提供相當大的診斷功能,接近最后,你會看到EPERM的內容.
要解決此問題,您可以在PHP中使用chdir來設置當前工作目錄,也可以在腳本中使用cd,或者您的腳本可以使用絕對路徑.我更喜歡后者.
標簽:php,shell,command-line,sh
來源: https://codeday.me/bug/20190627/1305955.html