pyenv/pyenv-virtualenv環境を構築する
必要なパッケージのインストール
pyenvはpythonをダウンロードしてきてコンパイルするけど、その際に必要となるパッケージを入れておく。Fedora以外はこちらを参照。
- Fedora 27
dnf install -y gcc zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel tk-devel xz
pyenvとpyenv-virtualenvのインストール
pyenv開発者がpyenv installerを公開しているのでそれを利用してインストールする。このインストーラがpyenv-virtualenvまで入れてくれるからラクチン。
$ curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash .... <snip> ... WARNING: seems you still have not added 'pyenv' to the load path. # Load pyenv automatically by adding # the following to ~/.bash_profile: export PATH="/home/hoge/.pyenv/bin:$PATH" eval "$(pyenv init -)" eval "$(pyenv virtualenv-init -)"
ということなので、.bashrc
に下記を追加しておく。
export PATH="/home/hoge/.pyenv/bin:$PATH" eval "$(pyenv init -)" eval "$(pyenv virtualenv-init -)"
pythonのバージョンをインストールしてみる
インストール可能なバージョンを確認
$ pyenv install --list ... 3.6.4 ...
特定バージョンのpythonをインストールする
$ python install 3.6.4 $ pyenv versions * system (set by /home/hoge/.pyenv/version) 3.6.4
新しい環境を作成してみる
システムのpythonのバージョンの確認
$ python --version Python 2.7.14
/home/hoge/hoge以下に3.6.4環境を作成してみる
$ cd /home/hoge/hoge $ pyenv virtulenv 3.6.4 my_3.6.4 $ pyenv local my_3.6.4 $ python --version Python 3.6.4 $ cd .. $ python --version Python 2.7.14
ということで、/home/hoge/hoge
以下だけ3.6.4を使う環境をつくれた
起動失敗してgrubプロンプト(grub >)が出た場合の対処
調べるのが面倒なので、メモを残しておく。
1. パーティションの確認 (sda2から起動したい)
grub> ls (hd0) (hd0,msdos3) (hd0,msdos2) (hd0,msdos1)
2. パーティションの中身の確認
grub> ls (hd0,msdos2)/ bin/ boot/ dev/ .... grub> cat (hd0,msdos2)/etc/redhat-releases Fedora release 27 (Twenty Seven) grub> ls (hd0,msdos)/boot/ .... initramfs-4.14-11-300.fc27.x86_64.img .... vmlinuz-4.14.11-300.fc27.x86_64 ...
3. 起動
grub> set root=(hd0,msdos2) grub> linux /boot/vmlinux-4.14.11-300.fc27.x86_64 root=/dev/sda2 grub> initrd /boot/initramfs-4.14.11-300.fc27.x86_64.img grub> boot
4 (必要に応じて) grubの再インストール
# grub2-install /dev/sda
5 (必要に応じて) ファイルシステムの復旧
今回はxfsが壊れていたので下記コマンドを実行。
# xfs_repair /dev/sda2
参考
https://jp.linux.com/news/linuxcom-exclusive/418274-lco20140625 26.7. GRUB 2 の再インストール Red Hat Enterprise Linux 7 | Red Hat Customer Portal
psコマンドでプロセスの親子関係を表示する
今までps aux
使ってたけど、f
付けるだけで分かり易くなるの知らなかった。
$ ps auxf USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND ... hoge 1981 0.0 0.1 534500 53764 tty2 S+ 23:19 0:00 \_ /opt/google/chrome/chrome --type=zygote hoge 1982 0.0 0.0 148140 13112 tty2 S+ 23:19 0:00 | \_ /opt/google/chrome/nacl_helper hoge 1985 0.0 0.0 534500 12308 tty2 S+ 23:19 0:00 | \_ /opt/google/chrome/chrome --type=zygote hoge 2163 0.0 0.2 991548 83072 tty2 Sl+ 23:19 0:00 | \_ /opt/google/chrome/chrome --type=renderer --field-trial-handle=1715498460 ...
インスタンスにパスワードでログインする
Fedora等のイメージはデフォルトではパスワードログインが無効になってて、パスワードでログインすることができません。 しかし、CloudInit使って設定を変えることでパスワードログインできるようになります。
以下をユーザデータとして渡せばOK。 Horizonでインスタンスを作る際、Post-Creation -> Customization Script Source -> Direct Inputとして下記を入力。
#cloud-config password: <password> chpasswd: { expire: False } ssh_pwauth: True
pthread_once()について
pthread_once()
の使い方がよくわからなかったので調べてみた。
このページ(*)が分り易かったからまとめておく。
1. 用途
-初期化に使う --通常初期化はプログラムの開始時に実施*1 --でも、できない場合もある ---例えば、ライブラリを作成する場合、初期化してもらえるかわからん ---仕方ないから呼ばれた時に呼ばれた側で初期化しよう ---エントリポイントのすべてで初期化されたかを判定して初期化処理を書くのは馬鹿らしい --一回だけ実行する仕組みを作ろうぜ
→ pthread_once()
2. 定義
int pthread_once( pthread_once_t * once_control, void (*init_routine)(void)); once_control:制御変数。PTHREAD_ONCE_INIT で初期化。 init_routine:1回だけ呼ばれる初期化用関数。
3. 使い方の例
(*)にあるプログラムを実行しようと思ったんだけど、once_main.cが見つからなかったので、書いてみた。
#include <stdio.h> #include <pthread.h> extern void *thread_func1(void *); extern void *thread_func2(void *); extern void *thread_func3(void *); extern void *thread_func4(void *); int main(void) { int i = 0, j = 0; int ret; pthread_t th[4]; fprintf(stderr, "main starts!\n"); ret = pthread_create(&th[i], NULL, thread_func1, NULL); if (ret != 0) { perror("pthread_create"); goto out; } ret = pthread_create(&th[++i], NULL, thread_func2, NULL); if (ret != 0) { perror("pthread_create"); goto out; } ret = pthread_create(&th[++i], NULL, thread_func3, NULL); if (ret != 0) { perror("pthread_create"); goto out; } ret = pthread_create(&th[++i], NULL, thread_func4, NULL); if (ret != 0) { perror("pthread_create"); goto out; } out: while (j < i) pthread_join(th[j++], NULL); fprintf(stderr, "main ends\n"); return 0; }
これとonce_thread.cをビルドして実行するとこんな感じ。
$ ./once main starts! in thread_func2, before once_func. in thread_func3, before once_func. in thread_func1, before once_func. in thread_func4, now start. initializing function Start!! in thread_func4, now end. initializing function End... in thread_func2, after once_func. in thread_func3, after once_func. in thread_func2, mutex_lock OK. in thread_func1, after once_func. in thread_func2, mutex_unlock OK. in thread_func2, timesec:[5.000698] in thread_func3, mutex_lock OK. in thread_func3, mutex_unlock OK. in thread_func3, timesec:[6.001000] in thread_func1, mutex_lock OK. in thread_func1, mutex_unlock OK. in thread_func1, timesec:[7.001423] main ends
pthread_once()
で実行するonce_func()
は一度のみ実行されているし、同時に実行している他のスレッドはblockしてるのがわかる。
今日はここまで。
_smp_mflags
kernelのSRPMを展開して得られるSPECファイルを見るとビルドのところに、_smp_mflagsというのが出てくる。例えば、kernel.specだとこんな感じ。
BuildKernel() { MakeTarget=$1 KernelImage=$2 Flavour=$3 InstallName=${4:-vmlinuz} <snip> make -s ARCH=$Arch oldnoconfig >/dev/null make -s ARCH=$Arch V=1 %{?_smp_mflags} $MakeTarget %{?sparse_mflags} make -s ARCH=$Arch V=1 %{?_smp_mflags} modules %{?sparse_mflags} || exit 1 <snip>
で、この_smp_mflags
なんだが-jX
*1に展開されるのだけど、気が向いた時、ビルドの時間を短くするためにXをCPU数の2倍位にしたりすることがあったり。で、本当気が向いた時だけやってるので、SPECを手動で書き換えているのだけど、まあよく忘れるし、適当過ぎよねということで、さらっと調べてみたのでメモしておく*2。
まず、_smp_mflags
はrpmのマクロになります。で、rpmのマクロの定義は/usr/lib/rpm/
にある。マクロを定義しているファイルはいろいろあるので、grepしてみた。
$ grep -r _smp_mflags /usr/lib/rpm/ /usr/lib/rpm/platform/pentium3-linux/macros:%_smp_mflags %([ -z "$RPM_BUILD_NCPUS" ] \\\ /usr/lib/rpm/platform/x86_64-linux/macros:%_smp_mflags %([ -z "$RPM_BUILD_NCPUS" ] \\\ /usr/lib/rpm/platform/athlon-linux/macros:%_smp_mflags %([ -z "$RPM_BUILD_NCPUS" ] \\\ /usr/lib/rpm/platform/noarch-linux/macros:%_smp_mflags %([ -z "$RPM_BUILD_NCPUS" ] \\\ /usr/lib/rpm/platform/i486-linux/macros:%_smp_mflags %([ -z "$RPM_BUILD_NCPUS" ] \\\ /usr/lib/rpm/platform/i686-linux/macros:%_smp_mflags %([ -z "$RPM_BUILD_NCPUS" ] \\\ /usr/lib/rpm/platform/pentium4-linux/macros:%_smp_mflags %([ -z "$RPM_BUILD_NCPUS" ] \\\ /usr/lib/rpm/platform/ia32e-linux/macros:%_smp_mflags %([ -z "$RPM_BUILD_NCPUS" ] \\\ /usr/lib/rpm/platform/geode-linux/macros:%_smp_mflags %([ -z "$RPM_BUILD_NCPUS" ] \\\ /usr/lib/rpm/platform/amd64-linux/macros:%_smp_mflags %([ -z "$RPM_BUILD_NCPUS" ] \\\ /usr/lib/rpm/platform/i386-linux/macros:%_smp_mflags %([ -z "$RPM_BUILD_NCPUS" ] \\\ /usr/lib/rpm/platform/i586-linux/macros:%_smp_mflags %([ -z "$RPM_BUILD_NCPUS" ] \\\ /usr/lib/rpm/redhat/macros:%_smp_mflags %([ -z "$RPM_BUILD_NCPUS" ] \\\
まあ、こんな感じでたくさん出てくるわけだが、その中の/usr/lib/rpm/redhat/macros
を見てみると次のようになってた。
%_smp_mflags %([ -z "$RPM_BUILD_NCPUS" ] \\\ && RPM_BUILD_NCPUS="`/usr/bin/getconf _NPROCESSORS_ONLN`"; \\\ if [ "$RPM_BUILD_NCPUS" -gt 16 ]; then echo "-j16"; \\\ elif [ "$RPM_BUILD_NCPUS" -gt 1 ]; then echo "-j$RPM_BUILD_NCPUS"; fi)
RPM_BUILD_NCPUSが0だったらgetconf _NPROCESSORS_ONLN
の結果を代入する。
sysconf(3)のmanを見たら、_SC_NPROCESSORS_ONLN
は現在オンラインのCPU数を返すとのことなので、getconfでも同じと思われ、_smp_mflags
には現在オンラインのCPU数が入るはず。これで_smp_mflagsの定義が分かりましたとさ。
このマクロファイルをいじってあげれば、好きに設定できると。今度は忘れないようにしましょう。
(追記) マクロの中身を確認するのに、なにも/usr/lib/rpm/以下をgrepしなくてもよいみたい。rpmコマンドで調べられる模様。
$ rpm --eval %macro
macroの部分に知りたいマクロを入れればOK。