Armadilloフォーラム

コンテナ起動時にlighttpd自動起動

k.sato

2023年8月8日 13時11分

佐藤と申します。
お世話になっております。

●Armadillo-640/IoT(A6):Webブラウザの画面から制御(lighttpd+php-cgiを使用)
https://armadillo.atmark-techno.com/blog/615/12832
上記を参考にコンテナにlighttpdをインストールし、

lighttpd -f /etc/lighttpd/lighttpd.conf

コマンドでWebサーバを起動し動作確認が出来ました。

そこでコンテナ起動時にWebサーバを自動起動するにはどうすればよろしいでしょうか?

以上、よろしくお願い致します。

コメント

at_dominique.m…

2023年8月8日 13時34分

佐藤さん

お世話になっています、
マルティネです。

> ●Armadillo-640/IoT(A6):Webブラウザの画面から制御(lighttpd+php-cgiを使用)
> https://armadillo.atmark-techno.com/blog/615/12832
>
> 上記を参考にコンテナにlighttpdをインストールし、

> lighttpd -f /etc/lighttpd/lighttpd.conf

> コマンドでWebサーバを起動し動作確認が出来ました。
>
> そこでコンテナ起動時にWebサーバを自動起動するにはどうすればよろしいでしょうか?

このブログの記事は debian リリースの armadillo 640/IoT A6 のための記事でしたが、
手順や上記のコマンドはコンテナの中で手動に実行しているということであってますか?

あっていたら、コンテナについていくつか確認させてください:
- 以前のフォーラムのスレッドで VSCode の python アプリケーションをコンテナで開発していましたが、同じコンテナで lighttpd を起動していますか?別のコンテナで作業していますか?
- lighttpd を実行できる確認は、現在実行中のコンテナでしょうか?すでにイメージとして保存されたコンテナでしょうか?(ボリューム以外のコンテナのデーターは podman build か podman commit のコマンド以外で変更が保存されませんので注意が必要です)

回答によってもう少し詳しく説明できますが、同じコンテナで起動したい場合はコンテナの set_command を少し調整すれば実行できます。
例えば、コンテナに /startup.sh スクリプトを追加して、/startup.sh で lighttpd を実行する後に python を実行すれば両方のプロセスを起動させることはできます。コンテナコンフィグに set_command /startup.sh で実行すれば完了です。
ただし、コンテナを vscode で更新すると今作った lighttpd のコンテナが上書きされますので、そこはご注意ください。できれば、ブログに説明されているインストール手順を vscode プロジェクトにある Dockerfile に書き直した方が後ほどの更新が必要になった時に困らないと思います。

別のコンテナでしたら、/etc/atmark/containers に新しいコンフィグを追加して、set_command lighttpd -D -f /etc/lighttpd/lighttpd.conf で lighttpd をバックグラウンドされないように設定しておけば実行できると思います。

よろしくお願いします。

マルティネ様

佐藤です。

回答ありがとうございます。

> このブログの記事は debian リリースの armadillo 640/IoT A6 のための記事でしたが、
> 手順や上記のコマンドはコンテナの中で手動に実行しているということであってますか?
あっています。

> - 以前のフォーラムのスレッドで VSCode の python アプリケーションをコンテナで開発していましたが、同じコンテナで lighttpd を起動していますか?別のコンテナで作業していますか?
同じコンテナで lighttpd を起動しています。

> - lighttpd を実行できる確認は、現在実行中のコンテナでしょうか?すでにイメージとして保存されたコンテナでしょうか?(ボリューム以外のコンテナのデーターは podman build か podman commit のコマンド以外で変更が保存されませんので注意が必要です)
現在実行中のコンテナでpython_app.confに

add_volumes /var/www/html:/var/www/html
add_volumes /etc/lighttpd:/etc/lighttpd

index.htmlやlighttpd.confを格納しています。

> 回答によってもう少し詳しく説明できますが、同じコンテナで起動したい場合はコンテナの set_command を少し調整すれば実行できます。
> 例えば、コンテナに /startup.sh スクリプトを追加して、/startup.sh で lighttpd を実行する後に python を実行すれば両方のプロセスを起動させることはできます。コンテナコンフィグに set_command /startup.sh で実行すれば完了です。
コンテナに /startup.sh スクリプトを追加してとは具体的にどういうことでしょうか?

lighttpd -f /etc/lighttpd/lighttpd.conf
python3 /vol_app/src/main.py

ATDE9のvscodeで python_app.confと同じディレクトリに startup.sh を作成し
上記としてみたのですが、podman ps で確認したときに python_app が落ちています。

> ただし、コンテナを vscode で更新すると今作った lighttpd のコンテナが上書きされますので、そこはご注意ください。できれば、ブログに説明されているインストール手順を vscode プロジェクトにある Dockerfile に書き直した方が後ほどの更新が必要になった時に困らないと思います。

# packages listed here will be installed in container
python3
python3-libgpiod
python3-serial
python3-spidev
lighttpd
php-cgi

上記をpackages.txtに記述していますが、
下記を参考に Dockerfile にインストール部分を記述した方がよいのでしょうか?
●Armadillo Base OS:コンテナでの開発を簡単にする方法
https://armadillo.atmark-techno.com/blog/15349/11535

COPY resource /root/

COPYを使用して作成した.htmlや.phpなどを格納するということでしょうか?

> 別のコンテナでしたら、/etc/atmark/containers に新しいコンフィグを追加して、set_command lighttpd -D -f /etc/lighttpd/lighttpd.conf で lighttpd をバックグラウンドされないように設定しておけば実行できると思います。
以前pythonのアプリでThreadで管理した方がグローバル変数でデータ共有しやすいと教えていただきそうしました。

php と pythonのデータ共有となるとコンテナを分けた方がよろしいのでしょうか?
同じコンテナだとデータ共有しやすいなどありますか?

at_dominique.m…

2023年8月8日 15時29分

佐藤さん、

さっそくの返事ありがとうございます。

> コンテナに /startup.sh スクリプトを追加してとは具体的にどういうことでしょうか?

> lighttpd -f /etc/lighttpd/lighttpd.conf
> python3 /vol_app/src/main.py

> ATDE9のvscodeで python_app.confと同じディレクトリに startup.sh を作成し
> 上記としてみたのですが、podman ps で確認したときに python_app が落ちています。

この内容で実行できると思いますが、何かのエラーが発生していますね。
podman logs python_app で原因が表示されると思います。
「permission denied」のエラーでしたら、startup.sh に実行 bit が設定されていないだけですので、直接実行ではなく sh で実行すれば実行出きるようになります:
set_command sh /startup.sh

> 上記をpackages.txtに記述していますが、
> 下記を参考に Dockerfile にインストール部分を記述した方がよいのでしょうか?

packages.txt にパッケージを追加して、add_volumes でコンフィグや php のページを転送しているのであれば問題ないと思います。
一つだけ気になるところは、「add_volumes /var/www/html:/var/www/html」と「add_volumes /etc/lighttpd:/etc/lighttpd」の両方のボリュームは ABOS の /var/www/html と /etc/lighttpd を使っていますのでメモリ上の overlay で保存されないディレクトリです。
python のソースの様に、「add_volumes www_html:/var/www/html<code>」と「<code>add_volumes www_etc:/etc/lighttpd」を設定すれば 「/var/app/rollback/volumes/www_html」 と 「/var/app/rollback/volumes/www_etc」に保存されて再起動で消えることはなくなります。

また、すでに設定しているかもしれませんが、コンテナコンフィグに「add_ports 80:80」 等のネットワーク設定も必要になると思います(lighttpd を実行できても、接続できなければ意味がないので)

> ●Armadillo Base OS:コンテナでの開発を簡単にする方法
> https://armadillo.atmark-techno.com/blog/15349/11535
>

> COPY resource /root/
> 

> COPYを使用して作成した.htmlや.phpなどを格納するということでしょうか?

コンフィグやページを編集しない場合は COPY をボリュームの代わりに使ってもいいですが、コンフィグを編集する度に新しいコンテナイメージを転送する必要がありますのでかなり不便になります。
今の(コンテナに OS の部分だけを管理して、コンフィグやデーターをボリュームで管理する)設定でいいと思います。

> > 別のコンテナでしたら、/etc/atmark/containers に新しいコンフィグを追加して、set_command lighttpd -D -f /etc/lighttpd/lighttpd.conf で lighttpd をバックグラウンドされないように設定しておけば実行できると思います。
> 以前pythonのアプリでThreadで管理した方がグローバル変数でデータ共有しやすいと教えていただきそうしました。
>
> php と pythonのデータ共有となるとコンテナを分けた方がよろしいのでしょうか?
> 同じコンテナだとデータ共有しやすいなどありますか?

php から python への通信方法によりますが、どちらでもいいと思います。
開発の面では同じコンテナで実行した方が管理しやすいので、とりあえずこのままで実装を続けて何かコンテナを別けた理由ができたら後で別けてもいいのではないでしょうか。
(例えば、ネットワークに接続しているコンテナを rs485 に直接アクセスできない様にしたい等のセキュリティな考えは、後で必要だと考えていた時に実装できます)

よろしくお願いします。

マルティネ様

佐藤です。

> この内容で実行できると思いますが、何かのエラーが発生していますね。
> podman logs python_app で原因が表示されると思います。
> 「permission denied」のエラーでしたら、startup.sh に実行 bit が設定されていないだけですので、直接実行ではなく sh で実行すれば実行出きるようになります:
> set_command sh /startup.sh
podman logs python_app
を実行してみたところ下記のエラーが発生し続けています。

CONTAINER ID  IMAGE       COMMAND     CREATED     STATUS      PORTS       NAMES
armadillo:~# podman logs python_app
ERROR (catatonit:2): failed to exec pid1: No such file or directory
ERROR (catatonit:2): failed to exec pid1: No such file or directory
ERROR (catatonit:2): failed to exec pid1: No such file or directory

> 一つだけ気になるところは、「add_volumes /var/www/html:/var/www/html」と「add_volumes /etc/lighttpd:/etc/lighttpd」の両方のボリュームは ABOS の /var/www/html と /etc/lighttpd を使っていますのでメモリ上の overlay で保存されないディレクトリです。
> python のソースの様に、「add_volumes www_html:/var/www/html<code>」と「<code>add_volumes www_etc:/etc/lighttpd」を設定すれば 「/var/app/rollback/volumes/www_html」 と 「/var/app/rollback/volumes/www_etc」に保存されて再起動で消えることはなくなります。
なるほどそうするのですね。
persist_file で保存するようにしましたが、そのように変更してみます。

> また、すでに設定しているかもしれませんが、コンテナコンフィグに「add_ports 80:80」 等のネットワーク設定も必要になると思います(lighttpd を実行できても、接続できなければ意味がないので)
親切にありがとうございます。
●10.2.7.1. HTTP サーバを構築する
https://manual.atmark-techno.com/armadillo-640/armadillo-640_product_ma…
を参考に add_ports 8080:80 としています。

連投ですみません。

佐藤です。

さきほど packages.txt を貼りましたが全てではありませんでした。
下記が全てです。

# packages listed here will be installed in container
python3
python3-libgpiod
python3-serial
python3-spidev
lighttpd
php-cgi
php-curl
php-mbstring
procps
vim
systemd

コンテナ内からのwebサーバの起動のさせ方がわからなく
下記を参考に systemctl してみたのですがうまくいかずに質問しました。
●Armadillo-X1, Armadillo-IoT G3/G3L: systemdでアプリを自動起動する方法(その1)
https://armadillo.atmark-techno.com/blog/6938/2865

これが影響しているのでしょうか?

at_dominique.m…

2023年8月8日 16時07分

> ERROR (catatonit:2): failed to exec pid1: No such file or directory

「そのようなファイルはありません」エラーですね。
「 /startup.sh」はコンテナのイメージに保存されてますか?

コンテナコンフィグに設定されている「set_command」と「podman run --rm python_app_image ls -l /startup.sh」の出力を提供していただけたらと思います(python_app_image はコンテナのイメージ名のデフォルト値ですが、変わっていたらそのイメージでお願いします)

startup.sh を vscode プロジェクトの container/resources/ に書いていたら、次にコンテナを更新するときにコピーされると思いますが、これも add_volumes startup.sh:/startup.sh で volume にしていたら Base OS の /var/app/rollback/volumes/startup.sh として管理できますね。

よろしくお願いします。

マルティネ様

佐藤です。

> 「そのようなファイルはありません」エラーですね。
> 「 /startup.sh」はコンテナのイメージに保存されてますか?
すみません。
> ATDE9のvscodeで python_app.confと同じディレクトリに startup.sh を作成し
なので添付画像の通り swu/python_app/etc/atmark/containers に作成していました。

> startup.sh を vscode プロジェクトの container/resources/ に書いていたら、次にコンテナを更新するときにコピーされると思いますが、これも add_volumes startup.sh:/startup.sh で volume にしていたら Base OS の /var/app/rollback/volumes/startup.sh として管理できますね。
上記を見て気付き container/resources/startup.sh にスクリプトファイルをコピーし再度swuを生成しました。

Armadillo Base OSの /etc/atmark/containers/python_app.conf の「set_command」は下記としています。

# launch app
#set_command python3 /vol_app/src/main.py
set_command /startup.sh

「podman run --rm python_app_image ls -l /startup.sh」の出力結果は下記となりました。

armadillo:~# podman run --rm python_app_image ls -l /startup.sh
-rw-r--r-- 1 root root 69 Aug  8 07:29 /startup.sh
ファイル ファイルの説明
atde9_vscode.png

この状態でもまだ python_app が起動しないため
podman logs python_app を実行したところ下記となりました。

armadillo:~# podman logs python_app
ERROR (catatonit:2): failed to exec pid1: Permission denied
ERROR (catatonit:2): failed to exec pid1: Permission denied
ERROR (catatonit:2): failed to exec pid1: Permission denied

> 「permission denied」のエラーでしたら、startup.sh に実行 bit が設定されていないだけですので、直接実行ではなく sh で実行すれば実行出きるようになります:
> set_command sh /startup.sh
これが言われていたエラーでしょうか?

at_dominique.m…

2023年8月8日 17時37分

佐藤さん、

> > ATDE9のvscodeで python_app.confと同じディレクトリに startup.sh を作成し
> なので添付画像の通り swu/python_app/etc/atmark/containers に作成していました。

添付画像までありがとうございます。

> # launch app
> #set_command python3 /vol_app/src/main.py
> set_command /startup.sh
[...]
> armadillo:~# podman run --rm python_app_image ls -l /startup.sh
> -rw-r--r-- 1 root root 69 Aug  8 07:29 /startup.sh

podman run でファイルがちゃんとありますので、"no such file or directory" のエラーは少し気になりますが (set_command の方に全角空白が混じったり?)、
この ls -l の出力では実行ビットが確かにないので、「set_command sh /startup.sh」で試して
再び「podman logs python_app」で確認していただけますか?

また失敗しちたら、「podman_start -v python_app」で実行されている podman コマンドも確認してみたいと思います。

(以前のメッセージの回答も同時にさせていただきます)

> systemd

> コンテナ内からのwebサーバの起動のさせ方がわからなく
> 下記を参考に systemctl してみたのですがうまくいかずに質問しました。
> ●Armadillo-X1, Armadillo-IoT G3/G3L: systemdでアプリを自動起動する方法(その1)
> https://armadillo.atmark-techno.com/blog/6938/2865
>
> これが影響しているのでしょうか?

これは関係ないと思いますが、説明のため、systemd のパッケージをインストールしても、systemd が自動てきに実行されません。
set_command を変更して systemd を実行すれば、init として systemd でサービスを管理できるようになります。コンフィグファイルで書くと以下の設定になります(set_init は、デフォルトで別の小さい init を使っているために systemd の場合に無効化します)

set_command /bin/systemd
set_init no

上記のコンフィグで systemd が実行されて、コンテナ内に設定しているサービスが実行されるはずです。
今回は systemd を使わなくてもいいと思いますが、必要になりましたら使えます。

よろしくお願いします。

マルティネ様

佐藤です。

> この ls -l の出力では実行ビットが確かにないので、「set_command sh /startup.sh」で試して
> 再び「podman logs python_app」で確認していただけますか?
set_command sh /startup.sh に変更したところ pythonアプリも lighttpd も起動するようになりました。
ありがとうございます。

●Armadillo-640/IoT(A6):Webブラウザの画面から制御(lighttpd+php-cgiを使用)
https://armadillo.atmark-techno.com/blog/615/12832

root@armadillo:~# chmod 666 /sys/class/leds/red/brightness
root@armadillo:~# chmod 666 /sys/class/leds/green/brightness
 
# /var/www/html/led_status.txtは、新規作成します。
root@armadillo:~# touch /var/www/html/led_status.txt
root@armadillo:~# chmod 666 /var/www/html/led_status.txt

上記のようなコンテナ内から権限を与えたい場合どうすればよろしいでしょうか?
Dockerfile もしくは python_app.conf に記述しておくことが出来るのでしょうか?

at_dominique.m…

2023年8月9日 8時00分

佐藤さん、

マルティネです。

> set_command sh /startup.sh に変更したところ pythonアプリも lighttpd も起動するようになりました。
> ありがとうございます。

よかったです。

> ●Armadillo-640/IoT(A6):Webブラウザの画面から制御(lighttpd+php-cgiを使用)
> https://armadillo.atmark-techno.com/blog/615/12832
>

> root@armadillo:~# chmod 666 /sys/class/leds/red/brightness
> root@armadillo:~# chmod 666 /sys/class/leds/green/brightness
>  
> # /var/www/html/led_status.txtは、新規作成します。
> root@armadillo:~# touch /var/www/html/led_status.txt
> root@armadillo:~# chmod 666 /var/www/html/led_status.txt
> 

> 上記のようなコンテナ内から権限を与えたい場合どうすればよろしいでしょうか?
> Dockerfile もしくは python_app.conf に記述しておくことが出来るのでしょうか?

/sys のファイルは Armadillo 上にしかないので、Dockerfile で設定できません。
python_app.conf にコマンドを入れたらコンテナを起動する前にホスト側で実行されて、そのままコンテナで使えるようになりますが、この場合は startup.sh の方がわかりやすいではないでしょうか。startup.sh は root ユーザーで実行されていますので、問題なくコンテナの設定はできます。

/var/www/html も add_volumes でコンテナイメージ内のファイルをシャドーしていますので、Dockerfile であらかじめ作成してもコンテナ起動時に見えないですね。
これも startup.sh で設定できますが、最初から php がかけるファイルに保存すればいいような気もします(例えば /tmp/led_status.txt にすれば、php の file_put_contents は何もせずにファイルを書き込みできると思います)。
eMMC に保存してもメリットがない内容なので、/tmp が適切だと思います。

よろしくお願いします。

マルティネ様

佐藤です。

> /sys のファイルは Armadillo 上にしかないので、Dockerfile で設定できません。
> python_app.conf にコマンドを入れたらコンテナを起動する前にホスト側で実行されて、そのままコンテナで使えるようになりますが、この場合は startup.sh の方がわかりやすいではないでしょうか。startup.sh は root ユーザーで実行されていますので、問題なくコンテナの設定はできます。
ありがとうございます。
startup.shに権限の追加を記述します。

> 一つだけ気になるところは、「add_volumes /var/www/html:/var/www/html」と「add_volumes /etc/lighttpd:/etc/lighttpd」の両方のボリュームは ABOS の /var/www/html と /etc/lighttpd を使っていますのでメモリ上の overlay で保存されないディレクトリです。
> python のソースの様に、「add_volumes www_html:/var/www/html」と「add_volumes www_etc:/etc/lighttpd」を設定すれば 「/var/app/rollback/volumes/www_html」 と 「/var/app/rollback/volumes/www_etc」に保存されて再起動で消えることはなくなります。

> startup.sh を vscode プロジェクトの container/resources/ に書いていたら、次にコンテナを更新するときにコピーされると思いますが、これも add_volumes startup.sh:/startup.sh で volume にしていたら Base OS の /var/app/rollback/volumes/startup.sh として管理できますね。

# web (lighttpd) server
#add_volumes /var/www/html:/var/www/html
#add_volumes /etc/lighttpd:/etc/lighttpd
#add_volumes /etc/php:/etc/php/8.2/cgi
add_volumes www_html:/var/www/html
add_volumes etc_lighttpd:/etc/lighttpd
add_volumes etc_php:/etc/php/8.2/cgi
 
# python & lighttpd 起動スクリプト
add_volumes startup.sh:/startup.sh

add_volumes について指摘がありましたので python_app.conf を修正しました。
この dev.swu を書き込み、起動したところ /var/app/rollback/volumes/ に下記が追加されました。

armadillo:~# ls /var/app/rollback/volumes/
etc_lighttpd  etc_php  python_app  startup.sh  www_html

生成される startup.sh はディレクトリのようだったので、削除してから権限を追加した startup.sh に置き換えました。
再起動したところ無事 python 、 lighttpd ともに起動しました。
この方法で問題ないでしょうか?

> これも startup.sh で設定できますが、最初から php がかけるファイルに保存すればいいような気もします(例えば /tmp/led_status.txt にすれば、php の file_put_contents は何もせずにファイルを書き込みできると思います)。
> eMMC に保存してもメリットがない内容なので、/tmp が適切だと思います。
こちらについても /tmp/led_status.txt に変更し、ブラウザでLEDステータスが確認できました。
ありがとうございました。

>> php と pythonのデータ共有となるとコンテナを分けた方がよろしいのでしょうか?
>> 同じコンテナだとデータ共有しやすいなどありますか?
> php から python への通信方法によりますが、どちらでもいいと思います。
少し前のコメントで「php から python への通信方法」についてありましたので
どうこれを実装するのか教えていただけませんか?

よろしくお願い致します。

at_dominique.m…

2023年8月9日 11時33分

佐藤さん、

> 生成される startup.sh はディレクトリのようだったので、削除してから権限を追加した startup.sh に置き換えました。

ファイルやディレクトリがない場合は podman がエラーしてしまいますので、ディレクトリとして作成されます。
あらかじめファイルを設置するとそのままに残していますので、これで大丈夫です。

> 再起動したところ無事 python 、 lighttpd ともに起動しました。
> この方法で問題ないでしょうか?

はい、問題なさそうです。

> >> php と pythonのデータ共有となるとコンテナを分けた方がよろしいのでしょうか?
> >> 同じコンテナだとデータ共有しやすいなどありますか?
> > php から python への通信方法によりますが、どちらでもいいと思います。
>
> 少し前のコメントで「php から python への通信方法」についてありましたので
> どうこれを実装するのか教えていただけませんか?

通信方法をまだ決めていませんでしたね。

これもいくらでも方法ありますが、別の言語なので socket で通信するのはどうでしょうか?
python 側で新しいスレッドで socket を bind/listen して、永遠に accept/処理するループ (参考 https://tokibito.hatenablog.com/entry/20150927/1443286053 )
php 側で stream_socket_client("unix:///path/to/python.sock", ..) で接続して fwrite/fgets で送信/受信を行えます ( https://www.php.net/manual/ja/function.stream-socket-client.php )

よろしくお願いします。

マルティネ様

佐藤です。

> これもいくらでも方法ありますが、別の言語なので socket で通信するのはどうでしょうか?
> python 側で新しいスレッドで socket を bind/listen して、永遠に accept/処理するループ (参考 https://tokibito.hatenablog.com/entry/20150927/1443286053 )
> php 側で stream_socket_client("unix:///path/to/python.sock", ..) で接続して fwrite/fgets で送信/受信を行えます ( https://www.php.net/manual/ja/function.stream-socket-client.php )
リンク先を試してみました。

pythonファイルは下記としました。

# server
class Server(threading.Thread):
    def __init__(self, socket_path):
        self.socket_path = socket_path
 
    def start(self):
        s = self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        s.bind(self.socket_path)
        s.listen(1)
        try:
            while True:
                connection, address = s.accept()
                sys.stdout.write("connected\n")
                self.accepted(connection, address)
                sys.stdout.write("disconnect\n")
        finally:
            os.remove(self.socket_path)
 
    def accepted(self, connection, address):
        """echo the received data
        """
        data = connection.recv(1024)
        sys.stdout.write("receive from client: {}\n".format(data.decode()))
        connection.send(data)
        sys.stdout.write("send to client: {}\n".format(data.decode()))
 
 
# main loop
if __name__ == '__main__':
    lock = Lock()
 
    t1 = Thread(target=spi.polling, args=(lock,))
    t2 = Thread(target=rs485.polling, args=(lock,))
    t3 = Server('/tmp/myapp.sock')
 
    t1.start()
    t2.start()
    t3.start()

phpファイルは下記としました。

<?php
    function send_client_to_server($text){
        print("send_client_to_server =".$text."\n");
 
        #$fp = stream_socket_client("unix:///path/to/python.sock", $errno, $errstr, 30);
        $fp = stream_socket_client("unix:///tmp/myapp.sock", $errno, $errstr, 30);
        if (!$fp) {
            echo "$errstr ($errno)<br />\n";
        } else {
            fwrite($fp, $text);
            while (!feof($fp)) {
                echo fgets($fp, 1024);
            }
            fclose($fp);
        }
    }
?>

POSTを受け send_client_to_server が呼ばれているようなのですが「No such file or directory (2)」となります。

stream_socket_client("unix:///path/to/python.sock", ..) この部分が存在しないのでしょうか?
このパスはpython側で生成される /tmp/myapp.sock を指定しなければなりませんか?
stream_socket_client("unix:///tmp/myapp.sock", ..) としたところ「Permission denied (13)」となりました。

chmod 777 /tmp/myapp.sock」で権限を与えるとvscodeのターミナルに下記と表示されました。

connected
receive from client: textBox
send to client: textBox
disconnect

> python 側で新しいスレッドで socket を bind/listen して...
というのはこういうことで合っているでしょうか?

chmod 666 /sys/class/leds/red/brightness
chmod 666 /sys/class/leds/green/brightness
 
touch /tmp/myapp.sock
chmod 777 /tmp/myapp.sock
 
lighttpd -f /etc/lighttpd/lighttpd.conf
python3 /vol_app/src/main.py

また、この権限の追加を上記のように startup.sh に追記してみたのですが下記のエラーが出るようになりました。

Traceback (most recent call last):
  File "/vol_app/src/main.py", line 115, in <module>
    t3.start()
  File "/vol_app/src/main.py", line 84, in start
    s.bind(self.socket_path)
OSError: [Errno 98] Address already in use

書き方や書く場所がおかしいのでしょうか?

at_dominique.m…

2023年8月9日 16時28分

佐藤さん、

マルティネです。

> stream_socket_client("unix:///path/to/python.sock", ..) この部分が存在しないのでしょうか?

はい、/path/to は例のつもりで書いただけです。 /tmp/myapp.sock でいいです。

> stream_socket_client("unix:///tmp/myapp.sock", ..) としたところ「Permission denied (13)」となりました。
>
> 「chmod 777 /tmp/myapp.sock」で権限を与えるとvscodeのターミナルに下記と表示されました。

はい、socket ファイルに書き込みの許可が必要です

> Traceback (most recent call last):
>   File "/vol_app/src/main.py", line 115, in <module>
>     t3.start()
>   File "/vol_app/src/main.py", line 84, in start
>     s.bind(self.socket_path)
> OSError: [Errno 98] Address already in use

> 書き方や書く場所がおかしいのでしょうか?

touch で一般ファイルを作ってしまったので、python でソケットを作成しようとするときにできなくなります。そのファイルは startup.sh ではなう、python で listen/bind の後にモードを直すといいです。

これ以降でarmadillo固有の処理はありません。pythonとphpの一般的な実装になりますが、想定されているシステムを実装するには委託開発程度にサポートする必要がありそうです。
時間のある時に答え続けますが、ある程度複雑なシステムを構築しているように見えますので、もし難易度が高い場合は弊社パートナーのご紹介も可能です。営業部までお問い合わせください。

お手数ですが、よろしくお願いします。

マルティネ様

佐藤です。

> touch で一般ファイルを作ってしまったので、python でソケットを作成しようとするときにできなくなります。そのファイルは startup.sh ではなう、python で listen/bind の後にモードを直すといいです。
listen/bind の後に os.chmod(self.socket_path, 0o0777)を追加したところ起動時に権限が追加されていました。

<?php
    function send_client_to_server($text){
        $fp = stream_socket_client("unix:///tmp/myapp.sock", $errno, $errstr, 30);
        if (!$fp) {
            echo "$errstr ($errno)<br />\n";
        } else {
            fwrite($fp, $text);
            while (!feof($fp)) {
                echo fgets($fp, 1024);
            }
            fclose($fp);
        }
    }
?>

また上記でecho fgets($fp, 1024);としていてvscodeのターミナルで確認しても送り返していそうなのですが
Timeout となり echo 表示しません。
受信できていないようなのですがどこが問題でしょうか?

> これ以降でarmadillo固有の処理はありません。pythonとphpの一般的な実装になりますが、想定されているシステムを実装するには委託開発程度にサポートする必要がありそうです。
> 時間のある時に答え続けますが、ある程度複雑なシステムを構築しているように見えますので、もし難易度が高い場合は弊社パートナーのご紹介も可能です。営業部までお問い合わせください。
長々と質問して申し訳ありません。
難しい場合はよろしくお願い致します。

>             while (!feof($fp)) {
>                 echo fgets($fp, 1024);
>             }
>             fclose($fp);
>         }
>     }
> ?>
> 

> また上記でecho fgets($fp, 1024);としていてvscodeのターミナルで確認しても送り返していそうなのですが
> Timeout となり echo 表示しません。
> 受信できていないようなのですがどこが問題でしょうか?

これも lighttpd で buffering されているだけかもしれません、python からすぐ close してなければ flush 類を追加してみてください
(英語) https://stackoverflow.com/questions/3133209/how-to-flush-output-after-e…

マルティネ様

佐藤です。

> これも lighttpd で buffering されているだけかもしれません、python からすぐ close してなければ flush 類を追加してみてください
> (英語) https://stackoverflow.com/questions/3133209/how-to-flush-output-after-e…

# server
class Server(threading.Thread):
    def __init__(self, socket_path):
        self.socket_path = socket_path
 
    def start(self):
        s = self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        s.bind(self.socket_path)
        s.listen(1)
        try:
            while True:
                connection, address = s.accept()
                sys.stdout.write("connected\n")
                self.accepted(connection, address)
                sys.stdout.write("disconnect\n")
        finally:
            os.remove(self.socket_path)
 
    def accepted(self, connection, address):
        """echo the received data
        """
        data = connection.recv(1024)
        sys.stdout.write("receive from client: {}\n".format(data.decode()))
        connection.send(data)
        sys.stdout.write("send to client: {}\n".format(data.decode()))

python側ですが close はしていないのですかね?
connection.send(data)」で終わっていそうです。

fwrite($fp, $text);
echo "fwrite after<br />\n";
$recv = null;
while (!feof($fp)) {
    $recv = fgets($fp, 1024);
    break;
}
echo "$recv<br />\n";
echo "fclose befor<br />\n";
fclose($fp);

php側ですが「$recv = fgets($fp, 1024);」してすぐ抜けるようにしましたが、
$fp = stream_socket_client("unix:///tmp/myapp.sock", $errno, $errstr, 30);」で指定している30秒後にタイムアウトで抜けて表示されます。
$recv = fgets($fp, 1024);」をコメントアウトすると即表示されます。
flush();」も追加してみましたが変わりませんでした。

よろしくお願い致します。

佐藤です。

連投ですみません。

# server
class Server(threading.Thread):
    def __init__(self, socket_path):
        self.socket_path = socket_path
 
    def start(self):
        s = self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        s.bind(self.socket_path)
        s.listen(1)
        try:
            while True:
                connection, address = s.accept()
                sys.stdout.write("connected\n")
                self.accepted(connection, address)
                sys.stdout.write("disconnect\n")
        finally:
            os.remove(self.socket_path)
 
    def accepted(self, connection, address):
        """echo the received data
        """
        data = connection.recv(1024)
        sys.stdout.write("receive from client: {}\n".format(data.decode()))
        connection.send(data)
        sys.stdout.write("send to client: {}\n".format(data.decode()))
        connection.close()

connection.send(data)」後に「connection.close()」することで、
php側の「echo fgets($fp, 1024);」で表示できることを確認しました。