VimでPythonのコード補完設定【cloudpack 大阪 BLOG】
最近はAWSのLambdaなどの開発でPythonを使うことが増えてきましたが、まだまだ慣れていないこともあり、ちょっとしたコードを書くにも関数名がわからないので都度ネットで調べないといけないのがすごくストレスでした。
開発環境としてはLinux上のVimで開発しているため、Vim上で動作するPluginがないか調べたところ「jedi-vim」というよさそうなpluginがあったため導入してみました。まだあまり使い込んでいませんが、コード補完だけでなく定義元への移動やPydocの閲覧もでき動作も軽いので結構気に入りました。
今回はjedi-vimの導入方法について紹介したいと思います。
導入手順
1.Neobundleのインストール
2.jedi-vimのインストール
3. 動作確認
Neobundleのインストール
以下のコマンドを実行
mkdir -p ~/.vim/bundle git clone https://github.com/Shougo/neobundle.vim ~/.vim/bundle/neobundle.vim
.vimrcに以下の設定を追加
if 0 | endif if has('vim_starting') if &compatible set nocompatible " Be iMproved endif " Required: set runtimepath+=~/.vim/bundle/neobundle.vim/ endif " Required: call neobundle#begin(expand('~/.vim/bundle/')) " Let NeoBundle manage NeoBundle " Required: NeoBundleFetch 'Shougo/neobundle.vim' " My Bundles here: " Refer to |:NeoBundle-examples|. " Note: You don't set neobundle setting in .gvimrc! call neobundle#end() " Required: filetype plugin indent on " If there are uninstalled bundles found on startup, " this will conveniently prompt you to install them. NeoBundleCheck
jedi-vimのインストール
以下のコマンドを実行
cd ~/.vim/bundle/
git clone --recursive https://github.com/davidhalter/jedi-vim.git
.vimrcに以下の設定を追加
" Jedi for python NeoBundleLazy "davidhalter/jedi-vim", { \ "autoload": { "filetypes": [ "python", "python3", "djangohtml"] }} if ! empty(neobundle#get("jedi-vim")) let g:jedi#auto_initialization = 1 let g:jedi#auto_vim_configuration = 1 nnoremap [jedi] <Nop> xnoremap [jedi] <Nop> nmap <Leader>j [jedi] xmap <Leader>j [jedi] let g:jedi#completions_command = "<C-Space>" # 補完キーの設定この場合はCtrl+Space let g:jedi#goto_assignments_command = "<C-g>" # 変数の宣言場所へジャンプ(Ctrl + g) let g:jedi#goto_definitions_command = "<C-d>" # クラス、関数定義にジャンプ(Gtrl + d) let g:jedi#documentation_command = "<C-k>" # Pydocを表示(Ctrl + k) let g:jedi#rename_command = "[jedi]r" let g:jedi#usages_command = "[jedi]n" let g:jedi#popup_select_first = 0 let g:jedi#popup_on_dot = 0 autocmd FileType python setlocal completeopt-=preview " for w/ neocomplete if ! empty(neobundle#get("neocomplete.vim")) autocmd FileType python setlocal omnifunc=jedi#completions let g:jedi#completions_enabled = 0 let g:jedi#auto_vim_configuration = 0 let g:neocomplete#force_omni_input_patterns.python = \ '\%([^. \t]\.\|^\s*@\|^\s*from\s.\+import \|^\s*from \|^\s*import \)\w*' endif endif
chrootの設定でハマった話【cloudpack 大阪 BLOG】
chrootの設定でかなりハマったので、今回はその内容をまとめたいと思います。
実現したいこと
sftp_userの接続時のホームディレクトリを「/home/sftp_user/home_dir」に制限したい。
意図は、bash_profile、bash_history、.sshなどをsftp接続ユーザーに見せたくないため
設定方法
ユーザー追加
useradd sftp_user passwd sftp_user
/etc/ssh/sshd_configの設定変更
#Subsystem sftp /usr/libexec/openssh/sftp-server
Subsystem sftp internal-sftp
Match User sftp_user
ChrootDirectory /home/sftp_user/home_dir
ForceCommand internal-sftp
PasswordAuthentication yes
sshd再起動
/usr/sbin/sshd -t ← 構文チェック service sshd restart
sshdサービス再起動は十分注意してください。再起動が失敗した場合、新たにssh接続ができなくなります。
クラウドサービスのように直接接続する手段がない場合に対応するときは、別でもう一つssh接続をしておくなど慎重に対応してください。
今回はAWSでの対応のため、起動失敗のままセッションを切ってしまうと接続できなくなってしまい、リカバリ対応がかなり大変になることが想定されました。
ディレクトリの設定
chown root:root /home/sftp_user/home_dir ←必須 chmod 755 /home/sftp_user/home_dir ←必須 mkdir /home/sftp_user/home_dir/data chmod 755 /home/sftp_user/home_dir/data
※「/home/sftp_user/home_dir/」にはsftp_userの書き込み権限がないため、書き込み可能なディレクトリを用意しておく必要があります。
接続確認
sftp sftp_user@IP_ADDR
でパスワードを入力して接続OK
これで対応完了!
としたかったのですが・・・
接続は鍵認証にしたかったようなので、接続用の鍵を作成し設定しました。
いざ接続確認してみるものの、Connection Refuse・・・
再度ユーザー作成し、sshで鍵認証ができることを確認してから上記対応を行うも接続出来ない状況でした。
/var/log/secureを確認しても芳しい情報は得られずでなかなか解決ができませんでした。
で、もう一度よく設定を見直すと今回chrootの設定先は「/home/sftp_user/home_dir」となります
そのため「/home/sftp_user」はroot権限に設定しているため、ssh接続時に鍵の参照ができてないため接続エラーとなっていることに気が付きました。
ということで上記のディレクトリ構成のままで鍵認証ができないことが分かったので、制限用のディレクトリは別途「/var/sftp/sftp_user」などにすることで解決しました。
貝塚 泉南 2015.11.29
EC2インスタンスにRaspberry Piで電源スイッチを付けてみた【cloudpack 大阪 BLOG】
久しぶりにRaspberryPiを触ってみて思いついたので早速作ってみました。以前はLチカやったところで終わっていましたが、Pythonを少し覚えたので何かAPIと連携させてみようと考えていました。最近、EC2インスタンスを触ることが多くなりましたが、サーバの電源を入れるということを全てWeb上でやっているので物理スイッチでわざわざ起動、停止をやってみようと思い作ってみました。
今回やってみたのは以下のような内容です。
・RaspberryPiでスイッチを押すとEC2が起動もしくは停止
・起動中 or 停止中はLEDを点滅させる
・起動、停止が完了したらslackで自分に通知
準備
RaspberryPi B+ (OSはraspbian 今回使用したバージョンは「Linux raspberrypi 3.12.28+ 」)
ブレッドボード
LED
タクトスイッチ
抵抗 330Ω(LED用)、1kΩ(タクトスイッチ用)
ジャンパーワイヤ
モジュールのインストール
pipのインストール
apt-get install python-pip
boto3(AWS SDK FOR Python)のインストール
pip install boto3
配線の確認
実際に部品が正しく配置されているか確認するため、下記のプログラムを実行して動作確認を行います。
LEDの動作確認
#! /usr/bin/env python import RPi.GPIO as GPIO import time LEDPIN = 21 GPIO.setwarnings(False) # Suppress warnings GPIO.setmode( GPIO.BCM ) GPIO.setup( LEDPIN, GPIO.OUT ) while 1: GPIO.output( LEDPIN, True ) time.sleep( 1.0 ) GPIO.output( LEDPIN, False ) time.sleep( 1.0 )
実行すると一定間隔でLEDが点滅します。点滅しなければ部品の配置や配線が間違えてないか見直してください
タクトスイッチの動作確認
#! /usr/bin/env python import RPi.GPIO as GPIO import time # define INPUT_PIN = 4 # init GPIO.setwarnings(False) # Suppress warnings GPIO.cleanup() GPIO.setmode(GPIO.BCM) GPIO.setup(INPUT_PIN,GPIO.IN) if __name__ == "__main__": Btn_Flag = False while True: print (GPIO.input(INPUT_PIN)) time.sleep(0.2)
実行してボタンを押すとボタンが押されている間はコンソールに「1」が表示されます
EC2インスタンスの起動・停止プログラム
上記のテストプログラムが正常に実行されれば実際にボタンを押してEC2のストップ、スタートができるプログラムを作成していきましょう。
AWSのアクセスキー、シークレットキー及びSlackのAPIキーは取得したものに変更してください。また、Slackの送信先は自身のユーザー名(@ + ユーザー名)に変更してください。
#! /usr/bin/env python import RPi.GPIO as GPIO import time import boto3 from boto3.session import Session import sys import urllib import urllib2 # define INPUT_PIN = 4 LEDPIN = 21 # init GPIO.setwarnings(False) # Suppress warnings GPIO.cleanup() GPIO.setmode(GPIO.BCM) GPIO.setup(INPUT_PIN,GPIO.IN) GPIO.setup( LEDPIN, GPIO.OUT ) ################################################################# # Function ################################################################# def getResourceEC2 (): session = Session(aws_access_key_id='ACCESS_KEY', aws_secret_access_key='SECRET_KEY', region_name='ap-northeast-1') ec2 = session.resource('ec2') return ec2 def get_ec2_state(instanceId): ec2 = getResourceEC2() instance = ec2.Instance(instanceId) if(instance.state['Name']=='running'): return True else: return False def start_ec2(instanceId): ec2 = getResourceEC2() instance = ec2.Instance(instanceId) if(instance.state['Name']=='stopped'): instance.start() # Flashing LED led_flag = False while instance.state['Name'] != 'running': GPIO.output( LEDPIN, not led_flag) led_flag = not led_flag instance.reload() time.sleep( 1.0 ) GPIO.output( LEDPIN, True) print('EC2 Start!') post_slack('EC2 Start!') else: print('EC2 already Started!') post_slack('EC2 already Started!') def stop_ec2(instanceId): ec2 = getResourceEC2() instance = ec2.Instance(instanceId) if(instance.state['Name']=='running'): instance.stop() # Flashing LED led_flag = False while instance.state['Name'] != 'stopped': GPIO.output( LEDPIN, not led_flag) led_flag = not led_flag instance.reload() time.sleep( 1.0 ) GPIO.output( LEDPIN, False) print('EC2 Stop!') post_slack('EC2 Stop!') else: print('EC2 already Stopped!') post_slack('EC2 already Stopped!') def post_slack(message): url = "https://slack.com/api/chat.postMessage" params = {'token' :'SLACK_API_KEY', 'channel':'@USER', 'text' : message } req = urllib2.Request(url) req.add_header('Content-Type', 'application/x-www-form-urlencoded') req.add_data(urllib.urlencode(params)) res = urllib2.urlopen(req) ################################################################# # Main Function ################################################################# if __name__ == "__main__": print('Switch Start') argvs = sys.argv Id = argvs[1] Btn_Flag = get_ec2_state(Id) GPIO.output( LEDPIN, Btn_Flag) while True: if(GPIO.input(INPUT_PIN)): Btn_Flag = not Btn_Flag if(Btn_Flag): start_ec2(Id) else: stop_ec2(Id) time.sleep(0.2)
※簡略化するため、ステータスチェックなど細かい処理は省いています。
泉南 2015.11.08
天候 :雨
今季初のタチウオでした。
貝塚 2015.11.03
天候 :曇
boto3(AWS SDK for Python)でCloudWatchからメトリクスを取得する【cloudpack 大阪 BLOG】
boto3を使ってCloudWatchからメトリクスを取得する必要が出てきたので勉強がてら簡単なサンプルを作ってみました。
環境
サーバ:CentOS6.6
Python:2.6.6
boto3:1.2.1
EC2インスタンスのメトリクスを取得のサンプル
まずはEC2のCPU使用率を取得してみたいと思います。
下記のコードを記載して適当なファイル名で保存してください。
import boto3 from boto3.session import Session import datetime import dateutil.tz import pprint pp = pprint.PrettyPrinter(indent=4) accesskey = "YOUR_ACCESSKEY" secretkey = "YOUR_SECRETKEY" region = "YOUR_REGION" session = Session( aws_access_key_id=accesskey, aws_secret_access_key=secretkey, region_name=region) client = session.client('cloudwatch') # Get EC2 CPUUtilization response = client.get_metric_statistics( Namespace='AWS/EC2', MetricName='CPUUtilization', Dimensions=[ { 'Name': 'InstanceId', 'Value': 'i-12345678' }, ], StartTime=datetime.datetime.utcnow() - datetime.timedelta(seconds=600), EndTime=datetime.datetime.utcnow(), Period=300, Statistics=['Average'] ) pp.pprint(response)
CloudWatchコンソール
リファレンスをななめ読みしただけですが、サイドメニューのMetricsがNamespaceとなりMetricNameが画面右側のMetricNameを指定します。Namespaceは「AWS/」をMetricsに付加すればよさそうです。(ここは後ほど書いてますが誤りでした)Dimensionsについては、取得したいサービスによって名称が異なるため、NameとValueを指定するようになっています。CPU使用率の場合はNameにInstanceIdをValueに実際のIDを指定します。
実行結果
python get_ec2_cpu.py { u'Datapoints': [ { u'Average': 0.20000000000000001, u'Timestamp': datetime.datetime(2015, 10, 31, 8, 16, tzinfo=tzutc()), u'Unit': 'Percent'}], u'Label': 'CPUUtilization', 'ResponseMetadata': { 'HTTPStatusCode': 200, 'RequestId': '1dfba5e6-7fa9-11e5-bc7c-1f8b347fd072'}}
EMRのメトリクスを取得
実際に取得したいMetricsは、EC2ではなくEMRのメトリクスを取得したかったのでEC2と同様にコードを書いてみましたが何故か取得できず。エラーは発生せず返却されるDatapointsの値に何もセットされていませんでした。スペルミスか時間指定が間違っているのかと思い見直すも問題はなさそうでした。そもそもNamespaceに問題があるのか?と疑いを抱き、list_metrics関数で取得してみると何も取得できませんでした。どうやら名前空間の指定に問題があるようで、調べてみると名前空間はAWS の名前空間 - Amazon CloudWatchで定義されていました。CloudWatchのMetricsと紐付くと思い込んでいましたがそうではないようです。今回は「AWS/ElasticMapReduce」と指定して正しく値を取得することができました。
response = client.get_metric_statistics( #Namespace='AWS/EMR', ←間違い Namespace='AWS/ElasticMapReduce', ←正 MetricName='IsIdle', Dimensions=[ { 'Name': 'JobFlowId', 'Value': 'j-1PNEZHM6MFON8' }, ], StartTime=datetime.datetime.utcnow() - datetime.timedelta(seconds=300), EndTime=datetime.datetime.utcnow(), Period=300, Statistics=['Average'] )
実行結果
python boto_sample.py { u'Datapoints': [ { u'Average': 1.0, u'Timestamp': datetime.datetime(2015, 10, 22, 9, 20, tzinfo=tzutc()), u'Unit': 'None'}], u'Label': 'IsIdle', 'ResponseMetadata': { 'HTTPStatusCode': 200, 'RequestId': '7c3a6076-8044-11e5-82dd-9bacba3e4791'}}