これまでずっと、ガッチャマンの南部博士の台詞を呟くbotを運用してきて、そろそろ宇門博士のも作らないとな、と思っていたら、APIの変更があって、これまでお世話になったEasyBotterが動かなくなってしまった。あたらしいTwitterOAuthを入れて修正しようとしたのだが、バージョンを少し上げたPHPでComposerを動かそうとすると、最新版を入れてあるにもかかわらずOpenSSLのライブラリを認識してくれず、パッケージ導入ができないという状態に。だったらPHPにこだわらずPythonでもいいだろ、と思ったので、Pythonでbotの復活を図った。ただ、Pythonはver.2系統がPloneのためにインストールされていて、混じると厄介なので、別ディレクトリに入れることにした。このため、関連ツールも含めてソースからコンパイルしていたのだが、これが結構嵌まった。

OpenSSLの最新版を入れる

まず,OpenSSLの最新版 openssl-1.1.1l.tar.gz をダウンロードして/usr/local/srcに入れる。
tar zxvf openssl-1.1.1l.tar.gz
cd openssl-1.1.1l
バージョンアップに備えて,/usr/local/openssl1.1.1の下にインストールする。
./config –prefix=/usr/local/openssl1.1.1 –openssldir=/usr/local/openssl1.1.1 -rpath=/usr/local/openssl1.1.1
すぐに終了してMakefileができるので,
make
make test

../test/recipes/05-test_md2.t …………………. skipped: md2 is not supported by this OpenSSL build
../test/recipes/05-test_rc5.t …………………. skipped: rc5 is not supported by this OpenSSL build
../test/recipes/30-test_afalg.t ……………….. skipped: test_afalg not supported for this build
../test/recipes/90-test_gost.t ………………… skipped: No test GOST engine found
../test/recipes/90-test_overhead.t …………….. skipped: Only supported in no-shared builds
../test/recipes/95-test_external_boringssl.t ……. skipped: No external tests in this configuration
../test/recipes/95-test_external_krb5.t ………… skipped: No external tests in this configuration
../test/recipes/95-test_external_pyca.t ………… skipped: No external tests in this configuration

が出るが,その他は全てokで,
Result: PASS
となったので,
make install

/usr/local/openssl1.1.1の下に,bin, include, libなどができている。
libの下は,
engines-1.1 libcrypto.so libssl.a libssl.so.1.1
libcrypto.a libcrypto.so.1.1 libssl.so pkgconfig
がある。

動作確認として,
/usr/local/openssl1.1.1/bin/openssl version -a
を実行すると,libssl.so.1.1が正常に作られているにもかかわらず,
Shared object “libssl.so.1.1” not found, required by “openssl”
と出る。
printenvすると,LD_LIBRARY_PATHが何も出ないので,試しに
setenv LD_LIBRARY_PATH /usr/local/openssl1.1.1/lib
してから再度実行すると,

OpenSSL 1.1.1l 24 Aug 2021
built on: Mon Nov 29 06:03:00 2021 UTC
platform: BSD-x86_64
options: bn(64,64) rc4(16x,int) des(int) idea(int) blowfish(ptr)

compiler: cc -fPIC -pthread -Wa,–noexecstack -Wall -O3 -rpath=/usr/local/openssl1.1.1 -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAESNI_ASM -DVPAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPOLY1305_ASM -D_THREAD_SAFE -D_REENTRANT -DNDEBUG
OPENSSLDIR: “/usr/local/openssl1.1.1”
ENGINESDIR: “/usr/local/openssl1.1.1/lib/engines-1.1”
Seeding source: os-specific

のように表示され,正常動作する。どうも,./configureで指定した–prefixが,ランタイムでは参照されていないっぽい。

curlを入れる

curl-7.80.0.tar.gzを/usr/local/srcに置く。

tar zxvf curl-7.80.0.tar.gz
cd curl-7.80.0
curlも,他で使っているものをぶつからないように,/usr/local/curl7.80.0にインストールする。

./configure –prefix=/usr/local/curl7.80.0 –with-ssl=/usr/local/openssl1.1.1/ –enable-libcurl-option

OpenSSLまわりは,
configure: PKG_CONFIG_LIBDIR will be set to “/usr/local/openssl1.1.1//lib/pkgconfig”
checking for pkg-config… (cached) /usr/local/bin/pkg-config
checking for openssl options with pkg-config… found
configure: pkg-config: SSL_LIBS: “-lssl -lcrypto “
configure: pkg-config: SSL_LDFLAGS: “-L/usr/local/openssl1.1.1/lib “
configure: pkg-config: SSL_CPPFLAGS: “-I/usr/local/openssl1.1.1/include “
checking for HMAC_Update in -lcrypto… yes
checking for SSL_connect in -lssl… yes
checking for openssl/x509.h… yes
checking for openssl/rsa.h… yes
checking for openssl/crypto.h… yes
checking for openssl/pem.h… yes
checking for openssl/ssl.h… yes
checking for openssl/err.h… yes
checking for RAND_egd… no
checking for SSLv2_client_method… no
checking for OpenSSL_version… yes
checking for BoringSSL… no
checking for libressl… no
checking for OpenSSL >= v3… no
configure: Added /usr/local/openssl1.1.1/lib to CURL_LIBRARY_PATH
checking for OpenSSL headers version… 1.1.1 – 0x111
checking for OpenSSL library version… 1.1.1
checking for OpenSSL headers and library versions matching… yes

となり,

CPPFLAGS: -isystem /usr/local/openssl1.1.1/include
LDFLAGS: -L/usr/local/openssl1.1.1/lib
LIBS: -lssl -lcrypto -lssl -lcrypto -lz

curl version: 7.80.0
SSL: enabled (OpenSSL)

となって,インストールしたOpenSSLはきちんと認識されている。

make
make test
make install

動作チェックは
/usr/local/curl7.80.0/bin/curl -V

curl 7.80.0 (x86_64-unknown-freebsd9.1) libcurl/7.80.0 OpenSSL/1.1.1l zlib/1.2.7
Release-Date: 2021-11-10
Protocols: dict file ftp ftps gopher gophers http https imap imaps mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS HSTS HTTPS-proxy IPv6 Largefile libz NTLM NTLM_WB SSL TLS-SRP UnixSockets

と表示されて,正常動作が確認できる。なお,
unsetenv LD_LIBRARY_PATH
してから実行すると,
Shared object “libssl.so.1.1” not found, required by “curl”
となり,やはりコンパイル時に与えたlibsslのありかがランタイムに反映されていない。

Pythonのインストール

最新版 Python-3.10.0.tgz を/usr/local/srcに置く。

tar zxvf Python-3.10.0.tgz
cd Python-3.10.0

インストール先を/usr/local/python3.10.0/にし,OpenSSLのインストール先/usr/local//openssl-1.1.1を指定して./configureする。

./configure –prefix /usr/local/python3.10.0/ –with-pydebug –with-openssl=/usr/local//openssl1.1.1 –with-ssl

checking for openssl/ssl.h in /usr/local//openssl1.1.1… yes
checking whether compiling and linking against OpenSSL works… yes

が出て,OpenSSLは認識されている。なぜパスの中に//が出てくるのかはよくわからない。

make

で出てくるメッセージの最後の方を見ると,

Python build finished successfully!
The necessary bits to build these optional modules were not found:
_gdbm _sqlite3 _tkinter
spwd
To find the necessary bits, look in setup.py in detect_modules() for the module’s name.

The following modules found by detect_modules() in setup.py, have been
built by the Makefile instead, as configured by the Setup files:
_abc pwd time

Failed to build these modules:
_ctypes

で,大丈夫そう。

make install

ls /usr/local/python3.10.0/bin/
で,pip3があることを確認。

/usr/local/python3.10.0/bin/pip3 list

他のメッセージとともに

Package Version
———- ——-
pip 21.2.3
setuptools 57.4.0

が表示された。
unsetenv LD_LIBRARY_PATH
してから実行しても同様のリストが出たので,pythonの実行では,LD_LIBRARY_PATHの設定が無くても,ランタイムにOpenSSLを見てくれているらしい。

tweepyを入れる

twitterAPI関連のツールをインストールする必要がある。今回はtweepyを使うことにする。

/usr/local/python3.10.0/bin/pip3 install tweepy

/usr/local/python3.10.0/lib/python3.10/site-packages/pip/_vendor/packaging/version.py:111: DeprecationWarning: Creating a LegacyVersion has been deprecated and will be removed in the next major release
warnings.warn(
/usr/local/python3.10.0/lib/python3.10/site-packages/pip/_internal/locations/_distutils.py:9: DeprecationWarning: The distutils package is deprecated and slated for removal in Python 3.12. Use setuptools or check PEP 632 for potential alternatives
from distutils.cmd import Command as DistutilsCommand
/usr/local/python3.10.0/lib/python3.10/distutils/command/install.py:13: DeprecationWarning: The distutils.sysconfig module is deprecated, use sysconfig instead
from distutils.sysconfig import get_config_vars
WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by ‘SSLError(“Can’t connect to HTTPS URL because the SSL module is not available.”)’: /simple/tweepy/
WARNING: Retrying (Retry(total=3, connect=None, read=None, redirect=None, status=None)) after connection broken by ‘SSLError(“Can’t connect to HTTPS URL because the SSL module is not available.”)’: /simple/tweepy/
WARNING: Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by ‘SSLError(“Can’t connect to HTTPS URL because the SSL module is not available.”)’: /simple/tweepy/
WARNING: Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by ‘SSLError(“Can’t connect to HTTPS URL because the SSL module is not available.”)’: /simple/tweepy/
WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by ‘SSLError(“Can’t connect to HTTPS URL because the SSL module is not available.”)’: /simple/tweepy/
Could not fetch URL https://pypi.org/simple/tweepy/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host=’pypi.org’, port=443): Max retries exceeded with url: /simple/tweepy/ (Caused by SSLError(“Can’t connect to HTTPS URL because the SSL module is not available.”)) – skipping
ERROR: Could not find a version that satisfies the requirement tweepy (from versions: none)
ERROR: No matching distribution found for tweepy
WARNING: You are using pip version 21.2.3; however, version 21.3.1 is available.
You should consider upgrading via the ‘/usr/local/python3.10.0/bin/python3.10 -m pip install –upgrade pip’ command.

で,OpenSSLまわりでコケまくってくれる。
ここまでどうってことなくOpenSSLが使えるようなメッセージを出しておきながら,いざ外部に接続しようとするとコケるのでは,どこまで遡って何をどう直せば良いかすぐにはわからない。これで大体丸一日悩む羽目になった。

pip3をローカルで動かす時に見ている場所と,実際にhttps接続する場合とではチェックするところが違うらしい。pythonでhttpsを使おうとしたときにLD_LIBRARY_PATHの設定が無いとコケそうな感じだが,cronで自動実行する予定なので,環境変数の設定の有無に依存するのではちょっと不安。

そこで,Pythonのソースディレクトリの下のModules/Setupを直接編集する。具体的には,OpenSSLへのパス指定と,スタティックリンクの場合の指定のコメントを外してOpenSSLをstatic linkさせる設定で再ビルドする。

OPENSSL=/usr/local/openssl1.1.1
# _ssl _ssl.c \
# -I$(OPENSSL)/include -L$(OPENSSL)/lib \
# -lssl -lcrypto
#_hashlib _hashopenssl.c \

# -I$(OPENSSL)/include -L$(OPENSSL)/lib \
# -lcrypto

# To statically link OpenSSL:
_ssl _ssl.c \
-I$(OPENSSL)/include -L$(OPENSSL)/lib \
-l:libssl.a -Wl,–exclude-libs,libssl.a \
-l:libcrypto.a -Wl,–exclude-libs,libcrypto.a
_hashlib _hashopenssl.c \
-I$(OPENSSL)/include -L$(OPENSSL)/lib \
-l:libcrypto.a -Wl,–exclude-libs,libcrypto.a

この変更をした上で,
cd ..
./configure –prefix /usr/local/python3.10.0/ –with-pydebug –with-openssl=/usr/local//openssl1.1.1 –with-ssl

checking for openssl/ssl.h in /usr/local//openssl1.1.1… yes
checking whether compiling and linking against OpenSSL works… yes

make clean
make

終わりの方のメッセージに

Python build finished successfully!
The necessary bits to build these optional modules were not found:
_gdbm _sqlite3 _tkinter
spwd

To find the necessary bits, look in setup.py in detect_modules() for the module’s name.

The following modules found by detect_modules() in setup.py, have been
built by the Makefile instead, as configured by the Setup files:
_abc _hashlib _ssl
pwd time

Failed to build these modules:
_ctypes

となり,今度はsslが入ったぽい。ということで,

make install

/usr/local/python3.10.0/bin/pip3 list の結果は先ほどと同じ。

/usr/local/python3.10.0/bin/pip3 install tweepy

/usr/local/python3.10.0/lib/python3.10/site-packages/pip/_vendor/packaging/version.py:111: DeprecationWarning: Creating a LegacyVersion has been deprecated and will be removed in the next major release
warnings.warn(
/usr/local/python3.10.0/lib/python3.10/site-packages/pip/_internal/locations/_distutils.py:9: DeprecationWarning: The distutils package is deprecated and slated for removal in Python 3.12. Use setuptools or check PEP 632 for potential alternatives
from distutils.cmd import Command as DistutilsCommand
/usr/local/python3.10.0/lib/python3.10/distutils/command/install.py:13: DeprecationWarning: The distutils.sysconfig module is deprecated, use sysconfig instead
from distutils.sysconfig import get_config_vars
/usr/local/python3.10.0/lib/python3.10/site-packages/pip/_vendor/packaging/version.py:111: DeprecationWarning: Creating a LegacyVersion has been deprecated and will be removed in the next major release
warnings.warn(
Collecting tweepy
Downloading tweepy-4.4.0-py2.py3-none-any.whl (65 kB)
|████████████████████████████████| 65 kB 1.1 MB/s

Collecting requests-oauthlib<2,>=1.0.0
Downloading requests_oauthlib-1.3.0-py2.py3-none-any.whl (23 kB)
Collecting requests<3,>=2.11.1
Downloading requests-2.26.0-py2.py3-none-any.whl (62 kB)
|████████████████████████████████| 62 kB 843 kB/s

Collecting idna<4,>=2.5
Downloading idna-3.3-py3-none-any.whl (61 kB)
|████████████████████████████████| 61 kB 5.2 MB/s

Collecting urllib3<1.27,>=1.21.1
Downloading urllib3-1.26.7-py2.py3-none-any.whl (138 kB)
|████████████████████████████████| 138 kB 4.5 MB/s

Collecting certifi>=2017.4.17
Downloading certifi-2021.10.8-py2.py3-none-any.whl (149 kB)
|████████████████████████████████| 149 kB 4.8 MB/s

Collecting charset-normalizer~=2.0.0
Downloading charset_normalizer-2.0.8-py3-none-any.whl (39 kB)
Collecting oauthlib>=3.0.0
Downloading oauthlib-3.1.1-py2.py3-none-any.whl (146 kB)
|████████████████████████████████| 146 kB 5.1 MB/s

Installing collected packages: urllib3, idna, charset-normalizer, certifi, requests, oauthlib, requests-oauthlib, tweepy
/usr/local/python3.10.0/lib/python3.10/site-packages/pip/_vendor/packaging/version.py:111: DeprecationWarning: Creating a LegacyVersion has been deprecated and will be removed in the next major release
warnings.warn(
Successfully installed certifi-2021.10.8 charset-normalizer-2.0.8 idna-3.3 oauthlib-3.1.1 requests-2.26.0 requests-oauthlib-1.3.0 tweepy-4.4.0 urllib3-1.26.7
WARNING: Running pip as the ‘root’ user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
WARNING: You are using pip version 21.2.3; however, version 21.3.1 is available.
You should consider upgrading via the ‘/usr/local/python3.10.0/bin/python3.10 -m pip install –upgrade pip’ command.

となって,rootのまま作業して怒られた以外は,依存関係にあるパッケージを全てインストールできた。/usr/local/python3.10.0/bin/pip3 list を実行すると,

Package Version
—————— ———
certifi 2021.10.8
charset-normalizer 2.0.8
idna 3.3
oauthlib 3.1.1
pip 21.2.3
requests 2.26.0
requests-oauthlib 1.3.0
setuptools 57.4.0
tweepy 4.4.0
urllib3 1.26.7

のように,依存関係のあるものが全部インストールされている。

インストール先は
/usr/local/python3.10.0/lib/python3.10/site-packages/
で,ここを ls で見ると,今いれたtweepyなどが入っていることが確認できる。

botのプログラム

次のプログラムを作成し,755で保存する。
つぶやきたいデータは改行で区切ったテキストファイルで,プログラムと同じディレクトリに置く(置かなくても実行はできるが,同じ場所にある方が管理が楽だろう)。sys.path.appendには,pip3でパッケージをインストールした時に表示される,インストール先のフルパスを書く。
Pythonはインデントでプログラムの実行ブロックを区別しているので,不必要なインデントをするとエラーになるから注意。また、プログラムファイルの改行コードがCRではうまくいかず、LFにする必要がありそう。うっかりエディタの設定がCRになってて、何のエラーメッセージもも出ないのになぜか動かないという状態になって暫く悩んだ。1行ずつインタプリタで実行したら、問題無く動いたので、改行コードの問題だと気づいたのだけど……。

——————————————————————————————————-

#!/usr/local/python3.10.0/bin/python3.10
# -*- coding: utf-8 -*-

import sys
sys.path.append(‘/usr/local/python3.10.0/lib/python3.10/site-packages/’)

import random
import tweepy

#********には、アプリケーションを登録した時にtwitter社から割り振られる4つのキーを書く。
CONSUMER_KEY = “***************************************”

CONSUMER_SECRET = “***************************************”
ACCESS_TOKEN = “***************************************”
ACCESS_TOKEN_SECRET = “***************************************”

auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
api = tweepy.API(auth ,wait_on_rate_limit = True)

#つぶやく内容を1つずつ改行で区切ったファイルを配列に読み込む。フルパス指定しないと環境によっては動かない。
with open(‘[path for data file]’, ‘r’) as f:
message = f.read().split(“\n”)

#配列の中身をシャッフル
random.shuffle(message)

#メッセージ内容チェック用(本番ではコメントアウト)
#print(message[0])

# つぶやく(本番ではこちらのコメントを外す)
api.update_status(message[0])

——————————————————————————————————-

シェルからファイル名を叩いて実行できることがわかったら、crontabに登録して定期的に実行させる。



Recently:


Comments


Name

Email

サイト

XHTML: 次のタグが使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

コメント

*