Linux用プロキシ設定いろいろ
プロキシ下でLinuxを使う際のメモ
を参考にした自分用のメモ
Fedora23 (Mate Desktop)を使用してプロキシ設定を行った
システム全体の設定
Fedora23では/etc/profile.d/
が存在したため/etc/profile.d/proxy.sh
を作成し,実行権限を与えた
$ sudo vi /etc/profile.d/proxy.sh HOST="ホスト名orホストIP" PORT="ポート" PROXY=${HOST}:${PORT} export http_proxy=http://${PROXY} export https_proxy=https://${PROXY} export ftp_proxy=ftp://${PROXY} export HTTP_PROXY=${http_proxy} export HTTPS_PROXY=${https_proxy} export FTP_PROXY=${ftp_proxy} local_ip=$(echo 192.168.1.{1..255}) local_ip=${local_ip// /,} export no_proxy=127.0.0.1,localhost,${local_ip} $ sudo chmod u+x /etc/profile.d/proxy.sh
しかし,これではFirefox等がネットにつながらなかったので,上記の設定はやめGUIから設定を行った
$ mate-network-properties
dnf
最終行にプロキシ設定を追加する
$ sudo vi /etc/dnf/dnf.conf [main] gpgcheck=1 installonly_limit=3 clean_requirements_on_remove=true proxy=http://ホスト名:ポート
随時更新予定
References
virtualenvでOpenCVを使う
virtualenv上のpipではopencvをインストールできなかったが
Is it possible to run opencv (python binding) from a virtualenv? - Stack Overflow
に
I found the solution was that I had to copy over cv2.so and cv.py to the directory running the virtualenv, then pip install numpy. To do this on Ubuntu 12.04 I used.
とあった.
仮想環境の作成
$ mkvirtualenv --python /opt/python2.7.11/bin/python2.7 --no-site-packages opencv
OpenCVのインストール
$ sudo dnf -y install opencv-python
システムのPythonを使用してインストールされたパスの確認を行う
$ python -c "import cv; print cv.__file__" /usr/lib64/python2.7/site-packages/cv.pyc $ ls /usr/lib64/python2.7/site-packages/ | grep cv cv.py cv.pyc cv.pyo cv2.so
これらのファイルへのシンボリックリンクを仮想環境内に作成する
$ cd ${WORKON_HOME}/opencv/lib/python2.7/site-packages $ ln -s /usr/lib64/python2.7/site-packages/cv* ./
ここで,OpenCVで使用するnumpy
をインストールする
$ workon opencv (opencv)$ pip install numpy Successfully installed numpy-1.10.4
動作確認
$ workon opencv (opencv)$ python >>> import cv >>> import cv2
問題なくimportできた
PhpStormのインストールと初期設定
インストール環境
Fedora23にPhpStorm10.0.3をインストールした
$ cat /etc/redhat-release Fedora release 23 (Twenty Three)
ダウンロード
PhpStorm IDE :: JetBrains PhpStorm
のDownload Nowからダウンロードする
または,
$ wget https://download.jetbrains.com/webide/PhpStorm-10.0.3.tar.gz
PHP実行環境のインストール
$ sudo dnf -y install php-devel $ php --version PHP 5.6.18 (cli) (built: Feb 4 2016 12:03:13) Copyright (c) 1997-2016 The PHP Group Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
次に,PHPのデバッガをインストール
$ sudo dnf -y install php-pecl-xdebug
インストール・初期設定
$ tar xf PhpStorm-10.0.3.tar.gz $ cd PhpStorm-10.0.3/bin $ ./phpstorm.sh
PHP Interpreterの設定
File -> Settings
から以下の設定を行う
ローカルのPHP実行環境の設定
-> Languages&Frameworks -> PHP
を開き,
Interpreter:
の右の...
から
+
を押しPHP Executableを/usr/bin/php
にする.
LiveEditの設定
編集中のファイルのブラウザプレビューを自動的に更新するLiveEditを
Live Editing of HTML, CSS, and JavaScript
に従いインストールする
Google Chromeのインストール
LiveEditはGoogle Chromeしか対応していないのでGoogle Chromeをインストールする必要がある
- Chrome ブラウザからダウンロードしインストールする
- 拡張機能: JetBrains IDE Supportをインストールする
LiveEditプラグインのインストール
PhpStormのヘルプ(Live Edit)には
LiveEditはデフォルトでインストール&有効化されていると書いてあったが,
インストールされていなかったので以下の手順でインストールした
Plugins
の検索ボックスでLiveEditと検索Install JetBrains plugin...
をクリックInstall
をクリックする
再起動するとBuild, Execution, Deployment -> Debugger -> Live Edit
から設定できるようになる
(Update
をAuto in (ms)
に変更すると,CSSの変更等も自動で反映するようになる)
以上の手順でセットアップした後にRun -> Debug
(Ctrl + F9
)で自動リロードモードに入れる
その他
- 行番号を表示:
Editor -> General Appearance -> Show line numbers
- 空白を表示 :
Editor -> General Appearance -> Show whitespaces
Linuxでのユーザ/グループ操作
ユーザー管理
ユーザ作成
$ sudo useradd -u ${UID} --create-home ${USER_NAME}
UIDの変更
$ sudo usermod -u ${NEW_UID} ${USER_NAME} $ id uid=${NEW_UID}(${USER_NAME}) ...(省略)
パスワード変更
$ sudo passwd ${USER_NAME}
または
$ su ${USER_NAME} $ passwd
所属グループの管理
- 所属グループを追加
$ sudo gpasswd -a ${USER_NAME} ${GROUP}
- 所属グループを削除
$ sudo gpasswd -d ${USER_NAME} ${GROUP}
sudo
できるようにする
ユーザを
グループに追加する
$ sudo gpasswd -a ${USER_NAME} wheel
グループの管理
グループ作成
GIDの変更
$ sudo groupmod -g ${NEW_GID} ${GROUP_NAME}
PT3サーバ自動起動・シャットダウン用スクリプト
BIOSの設定
RTCで起動できる様に設定する
Asrock H77M-ITXの場合は
Advanced Screen -> ACPI Configuration -> RTC Alarm Power On
自動復帰の確認
以下のコマンドを実行し,3分後に自動的に起動されることを確認する
$ echo `date +%s -d +3min` | sudo tee /sys/class/rtc/rtc0/wakealarm $ sudo shutdown -h now
上記のコマンドで成功しない場合はrtcwake
を使用すると成功するかもしれません
スクリプト作成
とりあえず,スクリプト全体は以下の通り.
#!/bin/python # -*- coding: utf-8 -*- import subprocess import datetime import time import logging from logging.handlers import RotatingFileHandler SUDO_PASS="実行ユーザのパスワード\n" log_handler = RotatingFileHandler( filename="/var/www/html/epgrec/video/pt3_savepower.log", mode="a", maxBytes=1000000, backupCount=3, encoding="utf-8", delay=False ) # log_handler.setLevel(logging.INFO) log_handler.setFormatter( logging.Formatter("%(asctime)s - %(levelname)-8s - %(message)s") ) logger = logging.getLogger() logger.setLevel(logging.INFO) logger.addHandler(log_handler) def is_terminal_login(): stdout, stderr = subprocess.Popen( ["/usr/bin/who"], stdout=subprocess.PIPE, stderr=subprocess.PIPE ).communicate() result = len([line for line in stdout.split("\n") if not line == ""]) logger.info("[terminal]: %d" % result) return False if result is 0 else True def is_recording_at(): stdout, stderr = subprocess.Popen( ["sudo", "-S", "/bin/atq"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE ).communicate(SUDO_PASS) result = len([line for line in stdout.split("\n") if "=" in line]) logger.info("[rec_at ]: %d" % result) logger.debug(stdout) return False if result is 0 else True def is_recording_ps(): stdout, stderr = subprocess.Popen( ["/bin/ps", "-el"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE ).communicate() ps_recpt1 = [line for line in stdout.split("\n") if "recpt1" in line] result = len(ps_recpt1) logger.info("[rec_ps ]: %d" % result) logger.debug(stdout) return False if result is 0 else True def is_port_established(): stdout, stderr = subprocess.Popen( ["sudo", "-S", "/sbin/lsof", "-i", ":ssh,http,https"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE ).communicate(SUDO_PASS) port_est = [line for line in stdout.split("\n") if "ESTABLISHED" in line] result = len(port_est) logger.info("[port ]: %d" % result) logger.debug(stdout) return False if result is 0 else True def convert_timestr(atq_line): result = atq_line.replace("Jan", "01") result = result.replace("Feb", "02") result = result.replace("Mar", "03") result = result.replace("Apr", "04") result = result.replace("May", "05") result = result.replace("Jun", "06") result = result.replace("Jul", "07") result = result.replace("Aug", "08") result = result.replace("Sep", "09") result = result.replace("Oct", "10") result = result.replace("Nov", "11") return result.replace("Dec", "12") def get_at_schedules(): stdout, stderr = subprocess.Popen( ["sudo", "-S", "/bin/atq"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE ).communicate(SUDO_PASS) schedule = [] for line in stdout.split("\n"): if line is "": continue tmp = line.split() time_str = convert_timestr(" ".join([tmp[5], tmp[2], tmp[3], tmp[4]])) time_str = datetime.datetime.strptime(time_str, "%Y %m %d %H:%M:%S") unixtime = int(time.mktime(time_str.timetuple())) schedule.append(unixtime) return schedule def get_closest_schedule(): return sorted(get_at_schedules())[0] def is_scheduled(unixtime): return any(s == unixtime for s in get_at_schedules()) def set_getepg_schedule(unixtime): if is_scheduled(unixtime): logger.info("getepg is already scheduled") else: getepg_at = datetime.datetime.fromtimestamp(unixtime).strftime("%y%m%d%H%M") stdout, stderr = subprocess.Popen( ["/bin/at", "-f", "/var/www/html/epgrec/video/at_getepg.sh", "-t", getepg_at], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE ).communicate() logger.info("[getepg ]: %s" % datetime.datetime.fromtimestamp(unixtime)) def set_rtcwake(unixtime): logger.info("[wakeup ]: %s" % datetime.datetime.fromtimestamp(unixtime)) stdout, stderr = subprocess.Popen( ["sudo", "-S", "/usr/sbin/rtcwake", "-m", "off", "-t", str(unixtime)], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE ).communicate(SUDO_PASS) logger.debug(stdout) def main(): logger.info("=============== START LOGGING ===============") if any([ is_terminal_login(), is_recording_at(), is_recording_ps(), is_port_established() ]): logger.info("someone using") else: now = int(time.time()) closest_waketime = now + 1800 closest_schedule = get_closest_schedule() wake_to_record = closest_schedule - 300 wake_to_getepg = closest_schedule - 1800 getepg_time = wake_to_getepg + 300 logger.info("NOW : %s" % datetime.datetime.fromtimestamp(now)) logger.info("WEPG : %s" % datetime.datetime.fromtimestamp(wake_to_getepg)) logger.info("GEPG : %s" % datetime.datetime.fromtimestamp(getepg_time)) logger.info("WREC : %s" % datetime.datetime.fromtimestamp(wake_to_record)) logger.info("CLOSE: %s" % datetime.datetime.fromtimestamp(closest_schedule)) if wake_to_getepg > closest_waketime: set_getepg_schedule(getepg_time) set_rtcwake(wake_to_getepg) elif wake_to_record > closest_waketime: set_rtcwake(wake_to_record) else: logger.info("close to wakeup time") if __name__ == '__main__': main()
グローバルスコープ
SUDO_PASS
スクリプト実行ユーザーのパスワードを入れてsudo
を実行できるようにする。
"パスワード\n"
のように末尾に\n
が入っているが,これがパスワード入力後のエンターキーの代わりになる。log_handler
に循環ログを定義する
main()
is_terminal_login()
ターミナルにログインしているユーザがいるかis_recording_at()
録画中かをat
コマンドで確認is_recording_ps()
録画中かをps
コマンドで確認is_port_established()
ssh,http,httpsのポートが使用中(接続中)であるかを確認
で,サーバの使用状況を確認し,シャットダウンして問題がなければ,
now = int(time.time())
現在時刻closest_waketime = now + 1800
次回起動の最短時刻(シャットダウンした場合に現在時刻から1800秒以内に起動する必要がある場合はシャットダウンしないようにするための値)closest_schedule = get_closest_schedule()
一番近い録画開始時刻wake_to_record = closest_schedule - 300
録画のために起動する時間(起動から録画開始まで,300秒の余裕をもたせる)wake_to_getepg = closest_schedule - 1800
時間に余裕がある場合は録画開始の1800秒前に起動しEPGの更新を行うgetepg_time = wake_to_getepg + 300
EPGの更新を行う場合にEPGの更新を開始する時刻(起動からEPG更新開始まで,300秒の余裕をもたせる)
上で設定した時刻を使用し
- 時間に余裕がある(
wake_to_getepg > closest_waketime
)場合
at
にEPG取得のスケジュールを登録した後,rtcwake
でシステムを停止する - EPG更新の余裕がない(
wake_to_record > closest_waketime
)場合は
rtcwake
でシステムを停止するだけにする - それ以外の場合 現在時刻から30分以内に録画開始する必要があるのでPCへの負荷を考慮し,シャットダウンせずに待機する
is_terminal_login()
who
を使用し,ログイン中のユーザを取得する
以下のコマンドを実行し,行数を数えることでログイン中のユーザがいるかを判断する
$ who ユーザー名 pts/0 2016-01-23 18:42 (192.168.19.5) ユーザー名 pts/1 2016-01-23 19:09 (192.168.19.5)
who
の実行結果stdout
に対し,以下の処理をすることで行数を数える。
len([line for line in stdout.split("\n") if not line == ""])
who
の実行結果を\n
で分割すると
[ "ユーザ1...", "ユーザ2...", "" ]
のように最後の改行コード後にも文字列があるように分割されるので
if not line == ""
を入れている
is_recording_at()
atq
を使用し,実行中のatジョブを取得する
$ sudo atq 524 Fri Jan 29 00:29:00 2016 a ユーザー名 455 Sat Jan 23 02:30:00 2016 = ユーザー名 465 Sun Jan 24 03:45:00 2016 a ユーザー名 466 Sun Jan 24 12:15:00 2016 a ユーザー名 467 Sun Jan 24 09:35:00 2016 a ユーザー名
sudo atq
の実行結果stdout
に対し,以下の処理で=
を含む行数を数える。
len([line for line in stdout.split("\n") if "=" in line])
is_recording_ps()
ps
を使用し,recpt1
を使用しているプロセスがあるかを確認する
$ ps -el F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD ... 0 S 1000 2936 2935 0 82 2 - 68925 hrtime ? 00:00:00 recorder.php 0 S 1000 2940 2936 0 82 2 - 2902 wait ? 00:00:00 do-record.sh 0 S 1000 2941 2940 4 82 2 - 59385 pt3_dm ? 00:02:01 recpt1 0 S 0 2942 1 0 80 0 - 61852 poll_s ? 00:00:00 pcscd ...
ps -el
の実行結果stdout
に対し,以下の処理でrecpt1
を含む行数を数える。
len([line for line in stdout.split("\n") if "recpt1" in line])
is_port_established()
lsof
を使用し,ssh,http,https
が使用されているかを確認する
$ sudo lsof -i :ssh,http,https COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME sshd 1081 root 3u IPv4 17772 0t0 TCP *:ssh (LISTEN) sshd 1081 root 4u IPv6 17783 0t0 TCP *:ssh (LISTEN) nginx 1127 root 6u IPv4 18486 0t0 TCP *:http (LISTEN) nginx 1128 nginx 3u IPv4 27768 0t0 TCP PT3:http->192.168.19.5:34158 (ESTABLISHED) nginx 1128 nginx 6u IPv4 18486 0t0 TCP *:http (LISTEN) sshd 3032 root 3u IPv4 25384 0t0 TCP PT3:ssh->192.168.19.5:60890 (ESTABLISHED) sshd 3034 pt3 3u IPv4 25384 0t0 TCP PT3:ssh->192.168.19.5:60890 (ESTABLISHED) sshd 3043 root 3u IPv4 25436 0t0 TCP PT3:ssh->192.168.19.5:60902 (ESTABLISHED) sshd 3045 pt3 3u IPv4 25436 0t0 TCP PT3:ssh->192.168.19.5:60902 (ESTABLISHED)
sudo lsof -i :ssh,http,https
の実行結果stdout
に対し,以下の処理でESTABLISHED
を含む行数を数える。
len([line for line in stdout.split("\n") if "ESTABLISHED" in line])
get_at_schedule()
atq
でスケジュールされているスケジュールの各時刻をunixtimeに変換したリストを返す
atq
からは以下のフォーマットで出力されるので
467 Sun Jan 24 09:35:00 2016 a ユーザー名
以下のようにフォーマットを変更し
convert_timestr()
関数で月コード(Jan)を数値(01)に変換する
2016 01 24 09:35:00
この文字列を以下でunixtimeに変換する
time_str = datetime.datetime.strptime(time_str, "%Y %m %d %H:%M:%S") unixtime = int(time.mktime(time_str.timetuple()))
get_closest_schedule()
get_at_schedule()
から得られたunixtimeのリストをソートし,最小値(最も近いスケジュールのunixtime)を取得する
set_getepg_schedule()
引数のunixtimeの時刻にat
にEPG更新をスケジュールする
- サーバが自動起動される前に手動でサーバを起動した場合には同じ時刻に複数のEPG更新がスケジュールする可能性があるので
is_scheduled()
で引数のunixtimeの時刻にat
にスケジュールがないかを確認する at
は直接php(getepg.php
)を実行できないため,以下のシェルスクリプトを経由してスケジュールを登録する
#!/bin/bash /var/www/html/epgrec/getepg.php
set_rtcwake()
rtcwake
を使用し,自動起動時刻を設定する
また,rtcwake
を実行すると自動的にシャットダウンされる
スクリプトのcron実行
sudo
を含むスクリプトをcronで実行すると
sudo: sorry, you must have a tty to run sudo
と言われ実行できないのでttyなしでsudo
できるようにする
今回はPT3専用のサーバなので簡単に以下のように56行目のDefaults requiretty
をコメントアウトした
$ sudo visudo # Disable "ssh hostname sudo <cmd>", because it will show the password in clear. # You have to run "ssh -t hostname sudo <cmd>". # #Defaults requiretty
以上で実行できるはずなので10分ごとにスクリプトを実行するようにする
$ crontab -e */10 * * * * python /path/to/script.py
References
RaspberryPiのSDカード寿命対策
システムはRaspbian Jessie Liteを使用した
swapを停止する
swapの使用状況を確認
$ free total used free shared buffers cached Mem: 948108 100608 847500 6432 8008 62572 -/+ buffers/cache: 30028 918080 Swap: 102396 0 102396
/etc/fstab
に以下の記述があったため
# a swapfile is not a swap partition, no line here # use dphys-swapfile swap[on|off] for that
dphys-swapfile
を停止する
$ sudo sysv-rc-conf dphys-swapfile off
再起動して確認
$ sudo reboot $ free total used free shared buffers cached Mem: 948108 166408 781700 6432 7152 128220 -/+ buffers/cache: 31036 917072 Swap: 0 0 0
RAMDiskを使う
/var/log
をRAMDiskにする際はスクリプトを作る必要があるそうだが,問題がなかったので作成しない
/tmp
/var/tmp
/var/log
をtmpfsでマウントする
$ sudo vim /etc/fstab proc /proc proc defaults 0 0 /dev/mmcblk0p1 /boot vfat defaults 0 2 /dev/mmcblk0p2 / ext4 defaults,noatime 0 1 # a swapfile is not a swap partition, no line here # use dphys-swapfile swap[on|off] for that tmpfs /tmp tmpfs defaults,noatime 0 0 tmpfs /var/tmp tmpfs defaults,noatime 0 0 tmpfs /var/log tmpfs defaults,noatime 0 0
マウントできるか確認
$ sudo rm -rf /tmp/* && sudo mount /tmp $ sudo rm -rf /var/tmp/* && sudo mount /var/tmp $ sudo rm -rf /var/log/* && sudo mount /var/log $ df -h ... tmpfs 463M 0 463M 0% /tmp tmpfs 463M 0 463M 0% /var/tmp tmpfs 463M 0 463M 0% /var/log
一応,再起動したあとに確認
$ df -h tmpfs 463M 116K 463M 1% /var/log tmpfs 463M 0 463M 0% /var/tmp tmpfs 463M 0 463M 0% /tmp
順番は変わったが,ちゃんと動いてそう
Ubuntu15.10でdockerを動かす
インストール
$ sudo apt-get -y install docker.io
ユーザ設定
dockerグループではないユーザでは以下のようなエラーが出る
$ docker images FATA[0000] Get http://%2Fvar%2Frun%2Fdocker.sock/v1.18/images/json: dial unix /var/run/docker.sock: connect: permission denied. Are you trying to connect to a TLS-enabled daemon without TLS?
sudoするかdockerを使用するユーザをdockerグループに追加すればいいので
dockerグループに追加する
$ sudo groupadd docker $ sudo gpasswd -a ${USER} docker $ sudo systemctl restart docker $ sudo reboot
dockerを試す
$ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE $ docker pull centos latest: Pulling from centos 47d44cb6f252: Pull complete 838c1c5c4f83: Pull complete 5764f0a31317: Pull complete 60e65a8e4030: Pull complete centos:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security. Digest: sha256:8072bc7c66c3d5b633c3fddfc2bf12d5b4c2623f7004d9eed6aae70e0e99fbd7 Status: Downloaded newer image for centos:latest $ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE centos latest 60e65a8e4030 2 weeks ago 196.6 MB
イメージが準備出来たので コンテナを起動
$ docker run -it centos:latest [root@a7c6fef2e476 /]# whoami root [root@a7c6fef2e476 /]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) [root@a7c6fef2e476 /]# exit