hoge-hogeoのひきこもごも

インフラエンジニアだけど形を持ったインフラを触ったことがない人の徒然

SonarqubeでCoverage出したい話

備忘録。

忘れている何かがあるかもしれない。

資源

  • CentOS Linux release 7.2.1511 (Core)
  • Jenkins ver. 2.73.1
  • Java 1.8.0_111 Oracle Corporation (64-bit)
  • SonarQube Scanner 2.8

手順

  • 必要なソースをgit clone
  • ログDIRとか作る
  • Composer updateする
  • php unitをかける

f:id:hoge-hogeo:20180928111938p:plain

Excludeするソースとか指定はしておいた方がいい。(Coverageに影響が出る) f:id:hoge-hogeo:20180928111432p:plain

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="vendor/autoload.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false">
    <testsuites>
        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>

        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./app</directory>
        </whitelist>
    </filter>
    <logging>
        <log type="junit" target="result.xml" logIncompleteSkipped="false"/>
        <log type="coverage-clover" target="./index.xml"/>
    </logging>
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="QUEUE_DRIVER" value="sync"/>
        <env name="DB_DATABASE" value="test_database_hoge"/>
    </php>
</phpunit>

Sonarに結果が出力されていればOK f:id:hoge-hogeo:20180928113328p:plain

Sonarに結果が出ないときは、jenkinsのワークスペースにそれぞれの結果ファイルが出力されているか確認する。

$ head /var/lib/jenkins/workspace/SonarScanner_hogehogeAPI/index.xml 
<?xml version="1.0" encoding="UTF-8"?>
<coverage generated="1538102369">
  <project timestamp="1538102369">
    <package name="App\Console">
      <file name="/var/lib/jenkins/workspace/SonarScanner_hogehogeAPI/app/Console/Kernel.php">
        <class name="App\Console\Kernel" namespace="App\Console">
          <metrics complexity="2" methods="2" coveredmethods="2" conditionals="0" coveredconditionals="0" statements="4" coveredstatements="4" elements="6" coveredelements="6"/>
        </class>
        <line num="25" type="method" name="schedule" visibility="protected" complexity="1" crap="1" count="23"/>
        <line num="29" type="stmt" count="23"/>
$ head /var/lib/jenkins/workspace/SonarScanner_hogehogeAPI/result.xml 
<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
  <testsuite name="tests/Feature/Api/" tests="23" assertions="85" errors="0" failures="0" skipped="0" time="4.553398">
    <testsuite name="Tests\Feature\CreateChildTest" file="/var/lib/jenkins/workspace/SonarScanner_hogehogeAPI/tests/Feature/Api/Child/CreateChildTest.php" tests="9" assertions="17" errors="0" failures="0" skipped="0" time="1.940765">
      <testsuite name="Tests\Feature\CreateChildTest::testValidation" tests="4" assertions="8" errors="0" failures="0" skipped="0" time="0.628133">
        <testcase name="testValidation with data set &quot;0&quot;" class="Tests\Feature\CreateChildTest" classname="Tests.Feature.CreateChildTest" file="/var/lib/jenkins/workspace/SonarScanner_hogehogeAPI/tests/Feature/Api/Child/CreateChildTest.php" line="79" assertions="2" time="0.230536"/>
        <testcase name="testValidation with data set &quot;1&quot;" class="Tests\Feature\CreateChildTest" classname="Tests.Feature.CreateChildTest" file="/var/lib/jenkins/workspace/SonarScanner_hogehogeAPI/tests/Feature/Api/Child/CreateChildTest.php" line="79" assertions="2" time="0.134350"/>
        <testcase name="testValidation with data set &quot;2&quot;" class="Tests\Feature\CreateChildTest" classname="Tests.Feature.CreateChildTest" file="/var/lib/jenkins/workspace/SonarScanner_hogehogeAPI/tests/Feature/Api/Child/CreateChildTest.php" line="79" assertions="2" time="0.131509"/>
        <testcase name="testValidation with data set &quot;3&quot;" class="Tests\Feature\CreateChildTest" classname="Tests.Feature.CreateChildTest" file="/var/lib/jenkins/workspace/SonarScanner_hogehogeAPI/tests/Feature/Api/Child/CreateChildTest.php" line="79" assertions="2" time="0.131738"/>
      </testsuite>

Systemctlのサービスを作る

参考

enakai00.hatenablog.com

enakai00.hatenablog.com

■serviceファイル作成

vim /usr/lib/systemd/system/nginx.service
############################################
[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIFfile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
ExecReload=/usr/bin/kill -s HUP $MAINPID
ExecStop=/usr/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
  
############################################

  
■list-unit-filesに認識されているか確認
$ sudo systemctl list-unit-files --type=service|grep nginx
nginx.service                     disabled
  
■有効化する
$ sudo systemctl enable nginx.service
Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service.

確認

■起動確認
$ sudo systemctl start nginx.service
$ ps -ef|grep ngin
root      9887     1  0 16:29 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
nginx     9888  9887  0 16:29 ?        00:00:00 nginx: worker process
root      9971 32341  0 16:29 pts/1    00:00:00 grep --color=auto ngin
  
■systemctl statusで確認
□確認項目
・PIDがpsで引いたものと合致しているか
・ExecStart, ExecStartPreがそれぞれ動いたか
  
$ sudo systemctl status nginx.service
● nginx.service - nginx - high performance web server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2018-04-16 16:29:35 JST; 42s ago
     Docs: http://nginx.org/en/docs/
  Process: 9886 ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf (code=exited, status=0/SUCCESS)
  Process: 9883 ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf (code=exited, status=0/SUCCESS)
 Main PID: 9887 (nginx)
   CGroup: /system.slice/nginx.service
       ├─9887 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
       └─9888 nginx: worker process
Apr 16 16:29:35 ip-10-56-79-94.ap-northeast-1.compute.internal systemd[1]: Starting nginx - high performance web server...
Apr 16 16:29:35 ip-10-56-79-94.ap-northeast-1.compute.internal nginx[9883]: nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
Apr 16 16:29:35 ip-10-56-79-94.ap-northeast-1.compute.internal nginx[9883]: nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
Apr 16 16:29:35 ip-10-56-79-94.ap-northeast-1.compute.internal systemd[1]: Started nginx - high performance web server.
Hint: Some lines were ellipsized, use -l to show in full.
  
■停止確認
$ sudo systemctl stop nginx.service
$ ps -ef|grep ngin
root     14815 32341  0 16:34 pts/1    00:00:00 grep --color=auto ngin

文字列編集系shell芸

php.iniとかコメントアウトたくさんある系のconfをさらっと確認しよう。

コメントアウトgrep -v してみればいいかな。

$ grep -v "^;" /etc/php.ini
[PHP]




































engine = On

short_open_tag = Off

precision = 14

output_buffering = 4096


zlib.output_compression = Off



implicit_flush = Off

unserialize_callback_func =

serialize_precision = 17
~つづく~

長い。だるい

$ grep -v "^;" /etc/php.ini|perl -pe 's/^\n//g'
[PHP]
engine = On
short_open_tag = Off
precision = 14
output_buffering = 4096
zlib.output_compression = Off
implicit_flush = Off
unserialize_callback_func =
serialize_precision = 17
disable_functions =
disable_classes =
zend.enable_gc = On
expose_php = On
max_execution_time = 30
max_input_time = 60
memory_limit = 512M
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
display_errors = Off
display_startup_errors = Off
log_errors = On
~つづく~

見やすい

Apache Flinkに入門してみる

https://ci.apache.org/projects/flink/flink-docs-release-1.6/quickstart/setup_quickstart.html

チュートリアル見て入門してみる。

f:id:hoge-hogeo:20180922130103p:plain 下のターミナルで打った文字列が、上のターミナルでtailしてるログに吐かれていく。

f:id:hoge-hogeo:20180922153628p:plain

僕はこのダッシュボードで何を確認すればいいのか分からない()

Wikipedia編集履歴を見るサンプルに挑戦してみる

Apache Flink 1.6 Documentation: Monitoring the Wikipedia Edit Stream

$ mvn archetype:generate \
>     -DarchetypeGroupId=org.apache.flink \
>     -DarchetypeArtifactId=flink-quickstart-java \
>     -DarchetypeVersion=1.6.1 \
>     -DgroupId=wiki-edits \
>     -DartifactId=wiki-edits \
>     -Dversion=0.1 \
>     -Dpackage=wikiedits \
>     -DinteractiveMode=false
[INFO] Scanning for projects...
Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-clean-plugin/2.4.1/maven-clean-plugin-2.4.1.pom
Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-clean-plugin/2.4.1/maven-clean-plugin-2.4.1.pom (5 KB at 3.3 KB/sec)
Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-plugins/18/maven-plugins-18.pom
~すごいたくさんダウンロードが走る~
[INFO] Project created from Archetype in dir: /home/ec2-user/wiki-edits
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 41.550s
[INFO] Finished at: Sat Sep 22 06:38:31 UTC 2018
[INFO] Final Memory: 14M/55M
[INFO] ------------------------------------------------------------------------

無事完了したらしい。

中身確認

$ tree wiki-edits
wiki-edits
tqq pom.xml
mqq src
    mqq main
        tqq java
        x?? mqq wikiedits
        x??     tqq BatchJob.java
        x??     mqq StreamingJob.java
        mqq resources
            mqq log4j.properties

5 directories, 4 files

f:id:hoge-hogeo:20180922154420p:plain

なんかちょっとチュートリアルページと内容物違うくない???(treeの標準出力の文字化けはともかく)

と思ったら、スクラッチで書くなら消していいよってあったのでrmする。

$ rm wiki-edits/src/main/java/wikiedits/
BatchJob.java      StreamingJob.java

$ rm wiki-edits/src/main/java/wikiedits/*.java

$ ll wiki-edits/src/main/java/wikiedits/
total 0

Writing a Flink Programする

javaのソース読めるなら「The complete code so far is this:」まで読み飛ばして、直後のソースをコピペすればOKっぽい。

5年くらい前に研修でJavaやったけど、もう覚えてないので、ちまちま英文読んだわず。

wikipediaAnalysis.javaのソースコピったらビルドしてみる。

$ mvn clean package
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 25.263s
[INFO] Finished at: Sat Sep 22 07:34:27 UTC 2018
[INFO] Final Memory: 25M/91M
[INFO] ------------------------------------------------------------------------

実行?してみよう

$ mvn exec:java -Dexec.mainClass=wikiedits.WikipediaAnalysis
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

(Hmains,-6)
(.144.107.98,9)
(Awookie90,627)
(Curdle,10)
(1.228.228.71,-1)
(Hmains,-8)
(.44.228.14,19)
(Keroks,-22)
(Spintendo,-1)
(JL-Bot,426)
(Sandstein,1470)
(3.211.53.179,-12)
(.222.170.164,72)
(Lfstevens,47)
(Cowdy001,0)
(A00:23C4:8A00:A600:4D50:1A41:2EB5:BB7,-13)

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".あたりで、死んだかな?と思ったら、

標準出力がぽつぽつ流れてきた、できたのかな。

This should get you started with writing your own Flink programs.

こんなことが書かれてるので、あとでBonus Exerciseもやってみよう。

■分からんこと

ncコマンドをバックグラウンド実行すると、WindowWordCount.jarが上がらない。

ncコマンドを直打ちするとターミナルが返ってこなくて、別窓開かないといけないのがめんどくさい。

から、バックグラウンドでやるかー。と単純に考えてやってみたら、エラーががが。

$ ./bin/flink run examples/streaming/SocketWindowWordCount.jar --9000
Starting execution of program
No port specified. Please run 'SocketWindowWordCount --hostname <hostname> --port <port>', where hostname (localhost by default) and port is the address of the text server
To start a simple text server, run 'netcat -l <port>' and type the input text into the command line

The program didn't contain a Flink job. Perhaps you forgot to call execute() on the execution environment.

↓こんな感じで↓

#バックグランドで実行
$ nc -l 9000 > /dev/null 2>&1 &
[1] 3051

#プロセスの死活確認
$ jobs
[1]+  Running                 nc -l 9000 > /dev/null 2>&1 &

#Listen確認
$ sudo netstat -anp |grep 9000
tcp        0      0 0.0.0.0:9000            0.0.0.0:*               LISTEN      3051/nc
tcp6       0      0 :::9000                 :::*                    LISTEN      3051/nc
unix  2      [ ACC ]     STREAM     LISTENING     19000    3168/master          private/proxywrite

#SocketWindowWordCount起動
$ ./bin/flink run examples/streaming/SocketWindowWordCount.jar --9000
Starting execution of program
No port specified. Please run 'SocketWindowWordCount --hostname <hostname> --port <port>', where hostname (localhost by default) and port is the address of the text server
To start a simple text server, run 'netcat -l <port>' and type the input text into the command line

The program didn't contain a Flink job. Perhaps you forgot to call execute() on the execution environment.

???

分からん。

けど、入門なのでここで止まってても仕方ないので、いったん放置してみておこ。

pythonでRedisの大量データからttl一覧を取得したい(2)

Redisのキーってttl切れしても実はメモリ上には残ってて、volatile-lruとかが発生するまで残ってるんじゃね? getかttlとかで引けば消えるんじゃね?

っていう話が上がって、とりあえずscanしてttl引いてみよう、getしてみようという話。

スクリプト1

collect_key_by_pattern.py

概要

パターンマッチを指定してn件ずつscan

scan_result_${pattern}.txtにkeyを出力

INPUT/OUTPUT
IN/OUT 備考
INPUT なし
OUTPUT scan_result_${pattern}.txt
引数
$n 説明 備考
1 対象のRedis endpoint 127.0.0.1
2 scanに渡すmatchパターン refresh_token 成果物のファイル名に使われるので、「:」を渡すとファイル名にそのまま渡されて少しださい
3 scanに渡すrange 1000
ソース
#!/usr/bin/env
 
import sys
import redis
import logging
 
 
INITIAL_CUR = 0
REDIS_HOST = len(sys.argv) > 1 and sys.argv[1] or '127.0.0.1'
MATCH_PATTERN = len(sys.argv) > 2 and sys.argv[2] or ''
COUNT = len(sys.argv) > 3 and sys.argv[3] or '100'
OUTPUT = 'scan_result_' + MATCH_PATTERN + '.txt'
 
logger = logging.getLogger()
logger.setLevel(10)
# for file
fh = logging.FileHandler(OUTPUT)
logger.addHandler(fh)
 
def utf8(byte):
    if byte:
        return str(byte, 'utf-8')
 
if __name__ == '__main__':
    if len(sys.argv[1:]) < 3:
        sys.exit("Usage: %s <redis-endpoint> <match-pattern>" % sys.argv[0])
    r = redis.StrictRedis(host=REDIS_HOST, port=ほげ)
    next_cur = INITIAL_CUR
    while True:
        res_scan = r.scan(cursor=next_cur, match=MATCH_PATTERN + '*', count=COUNT)             # SCAN
        print(len(res_scan[1]))
        next_cur = res_scan[0]
        if res_scan[1]:
            for key in res_scan[1]:
                logger.info(utf8(key))
        if next_cur == INITIAL_CUR:
            break
実行
$ python36 collect_key_by_pattern.py 127.0.0.1 refresh_token 1000
$ 

とくに出力はしない

成果物
$ head scan_result_refresh_token.txt
refresh_token:76c1b0bca4097cb1d42d2aa9c694d1bdbce5cc94
refresh_token:299251bad808a5b71ef8b806c689182e328701d3
refresh_token:02be609d8f80183f22edca17217d06d43717d64f

スクリプト2

get_ttl.py

概要

key, ttlのフォーマットでファイル出力

ttl切れを判定し、あったらファイル出力

INPUT/OUTPUT
IN/OUT 備考
INPUT scan_result_${pattern}.txt
OUTPUT key_ttl.log, expired_keys.txt
引数
$n 説明 備考
1 対象のRedis endpoint 127.0.0.1
2 検索するキーを記載したファイル scan_result_laravel.txt
ソース
#!/usr/bin/env
#coding:utf-8
import sys
import redis
import pdb
import logging
 
REDIS_HOST = len(sys.argv) > 1 and sys.argv[1]
INPUT_FILE = len(sys.argv) > 2 and sys.argv[2]
KEY_TTL = 'key_ttl.log'
 
#logger1==========================================
logger = logging.getLogger('LoggingTest')
logger.setLevel(10)
fh = logging.FileHandler(KEY_TTL)
logger.addHandler(fh)
#logger1==========================================
 
#logger2==========================================
logger_for_output = logging.getLogger('logger_for_output')
logger_for_output.setLevel(10)
# for file
fh = logging.FileHandler('expired_keys.txt')
logger_for_output.addHandler(fh)
#logger2==========================================
 
def utf8(byte):
    if byte:
        return str(byte, 'utf-8')
 
if __name__ == '__main__':
    if len(sys.argv[1:]) < 2:
        sys.exit("Usage: %s <redis-endpoint> <input file>" % sys.argv[0])
    r = redis.StrictRedis(host=REDIS_HOST, port=ほげ)
    # keyを元にttlを抽出、"key ttl"のフォーマットで中間ファイルを出力
    with open(INPUT_FILE) as f:
        for key in f:
            key_ = key.rstrip('\n')
            res_ttl = r.ttl(key_)      # TTL
            logger.info('%s  %s', key_, res_ttl)
    # 中間ファイルからkey, ttlを抽出して、ttl切れがないか確認
    with open(KEY_TTL) as f:
        for key in f:
            if key.split()[1] <= '0':
                logger_for_output.info(key.rstrip('\n'))
実行
$ python36 get_ttl.py 127.0.0.1 scan_result_refresh_token.txt
$

特に何も出ない

成果物

ttlが設定されていないキーが出力された。(テストデータ)

$ head expired_keys.txt 
refresh_token:cfa85abcc28d616f46c78f3c289609db0a1b1526  -1
refresh_token:182433e52a42776f95ff871a79f21e2a3c4ee9c17  -1
refresh_token:182433e52a42776f95ff871a79f21e2a3c4ee9c11  -1

あとで、実際にRedisにデータを突っ込んで試してみよう。

ダメでも、scanしてRedis内のキーの割合を算出する程度の役には立つだろう。。。

pythonでRedisの大量データからttl一覧を取得したい

Redisに大量のLaravelセッションがあるが、特定のキーパターンについてttl一覧を取得したい。。。 

python分からないもぅマヂ無理。なので、↓のような感じで処理をする。

  • scan パターン count=100とかでキー一覧をつくる
  • キー一覧をfor分で回してttlを探す

キー一覧

scan

$ head laravel_session_list 
laravel:HogesjKCNLFusLnPbfiPk0ts7VOoxxEOuWyHogeo
laravel:HogeXJm1eOUp9r1TUJffwOIC8ZeanCQNCpLHogeo
laravel:Hogez8PBpIScAJEbEj5kmO69xImf5rOxiEBjHogeo

ttl取得py(get_ttl.py)

とりあえず、ハードコーディングでキーをセットしてttlを取ってみる

import sys
import redis

REDIS_HOST = len(sys.argv) > 1 and sys.argv[1] or '127.0.0.1'

if __name__ == '__main__':
    r = redis.StrictRedis(host=REDIS_HOST, port=ぽーとばんごー)
    res_ttl = r.ttl('laravel:HogeTMuDXt7IsuncXtJTfujY8U9Hitg84vsHogeo')
    print(res_ttl)

redis-cliで引いてみる

$ redis-cli -h ${REDIS_HOST} -p ${ぽーとばんごー} ttl laravel:HogeTMuDXt7IsuncXtJTfujY8U9Hitg84vsHogeo
(integer) 15431149

pythonで引いてみる

$ python36 get_ttl.py ${REDIS_HOST}
15431143

いけてそう。

for文でリストを回してみよう。

import sys
import redis

REDIS_HOST = len(sys.argv) > 1 and sys.argv[1] or '127.0.0.1'
OUTPUT = 'laravel_session_list'

if __name__ == '__main__':
    r = redis.StrictRedis(host=REDIS_HOST, port=ぽーとばんごー)
    with open(OUTPUT) as f:
        for key in f:
            res_ttl = r.ttl('key')      # TTL
            print(key, str(res_ttl))
$ python36 get_ttl.py ${REDIS_HOST}
laravel:HogesjKCNLFusLnPbfiPk0ts7VOoxxEOuWyHogeo
 -2
laravel:HogeXJm1eOUp9r1TUJffwOIC8ZeanCQNCpLHogeo
 -2
laravel:Hoge8PBpIScAJEbEj5kmO69xImf5rOxiEBjHogeo
 -2
laravel:HogewUfxMeBQy0LwegrvdEjLAfr6a4BX1y4Hogeo
 -2
laravel:HogeeuBdQkRGXNLConVcqom59Ha0782ID1OHogeo
 -2
laravel:HogeI3rIbkpkklmfxbG8RTbPyBiXloUsIl2Hogeo
 -2
laravel:HogeG9GHP7heioXpD4keWkG3HT3ZpXQ1iILHogeo
 -2
laravel:HogetvsL7yriP8r5v0H632Qm3SMKAxIJPzsHogeo
 -2
laravel:HogeHfAkYL5bFLfEUSFneGMfMdifbQYo4kZHogeo
 -2
laravel:Hoge1CEZuOeSuu3dwvO3iO6uPG6TvGR4lddHogeo
 -2

ふえぇ。。。なんかおかしい。。。もぅマヂ無理。

-2は存在しないキーを指定したときらしい。

$ redis-cli -h ${ホスト} -p ${ポート} ttl hogehoge
(integer) -2

デバッガがほしい。

27.3. pdb — Python デバッガ — Python 3.6.5 ドキュメント

あった。

pdb.set_trace()をソース中に書くとそこで止まるらしい、使ってみよう。

res_ttl = r.ttl('key')の直後にブレークポイントを置いてみる。

import sys
import redis
★import pdb


REDIS_HOST = len(sys.argv) > 1 and sys.argv[1] or '127.0.0.1'
OUTPUT = 'laravel_session_list'

if __name__ == '__main__':
    r = redis.StrictRedis(host=REDIS_HOST, port=ぽーとばんごー)
    with open(OUTPUT) as f:
        for key in f:
            res_ttl = r.ttl('key')      # TTL
            ★pdb.set_trace()
            print(key, str(res_ttl))

止まった。ので変数名とレスポンスの中身を覗いてみる。

$ python36 get_ttl.py ${REDIS_HOST}
> /path/to/get_ttl.py(25)<module>()
-> print(key, str(res_ttl))
(Pdb) print(key)
laravel:HogesjKCNLFusLnPbfiPk0ts7VOoxxEOuWyHogeo

(Pdb) print(res_ttl)
-2

keyをprintしたときに改行コードがある、気がする。

rstripというもので改行コードを消せるらしい。

www.lifewithpython.com

埋め込んでみる。

    with open(OUTPUT) as f:
        for key in f:
            print('key(before rstrip): %s' % key)
            print('key(after rstrip): %s' % key.rstrip('\n'))

実行

$ python36 get_ttl.py 
key(before rstrip): laravel:p4uLsjKCNLFusLnPbfiPk0ts7VOoxxEOuWyAfnpu

key(after rstrip): laravel:p4uLsjKCNLFusLnPbfiPk0ts7VOoxxEOuWyAfnpu
> /path/to/get_ttl.py(27)<module>()

できた。

これで、再度continueしながら検索してみる。

ソースはこんな

    with open(OUTPUT) as f:
        for key in f:
            #print('key(before rstrip): %s' % key)
            #print('key(after rstrip): %s' % key.rstrip('\n'))
            res_ttl = r.ttl(key.rstrip('\n'))      # TTL
            print(key, res_ttl)
            pdb.set_trace()
$ python36 get_ttl.py 
laravel:HogesjKCNLFusLnPbfiPk0ts7VOoxxEOuWyHogeo
 624535
> /path/to/get_ttl.py(23)<module>()
-> for key in f:
(Pdb) continue
laravel:HogeXJm1eOUp9r1TUJffwOIC8ZeanCQNCpLHogeo
 7182184
> /path/to/get_ttl.py(23)<module>()
-> for key in f:
(Pdb)

別窓でredis-cliを引いてみる。

> ttl laravel:HogesjKCNLFusLnPbfiPk0ts7VOoxxEOuWyHogeo
(integer) 624520
> ttl laravel:HogeXJm1eOUp9r1TUJffwOIC8ZeanCQNCpLHogeo
(integer) 7182168

出来てそう。

redisに大量データを投入したい

脳死bashマンだから

 

for i in `seq 1 1000000`;do redis-cli -h $ホスト setex key$i $ttl val;done

 

とか書いてたけど、めっちゃ遅い。

 

luaで書いたら早かった。100万件で4秒以下。

 

> eval "for i = 1, 1000000 do redis.call('setex', i, 300, 1111111111) end" 0
(nil)
(3.69s)

 

> info

~中略~

# Keyspace
db0:keys=1000000,expires=1000000,avg_ttl=185692

 

redis-cliの引数にlua渡してサクサク作ったらもっと便利そう。