레이블이 computer인 게시물을 표시합니다. 모든 게시물 표시
레이블이 computer인 게시물을 표시합니다. 모든 게시물 표시

[컴][파이썬] No module named 'MySQLdb' 에러

import mysqldb

No module named 'MySQLdb' 에러

환경

  • 환경 : windows 10 , Windows Subsytem for Linux(WSL)
  • celery : version 4.4.2
  • SQLAlchemy : v1.3.17

설치된 packages

celery==4.4.2
SQLAlchemy==1.3.17
mysql-connector-python-rf==2.2.2

No module named 'MySQLdb'

이 상황에서 celery 의 task 를 실행시켰는데, 아래처럼 error 가 떴다. No module named 'MySQLdb' 가 주요한 이유였다.
[2020-06-01 14:26:50,785: WARNING/ForkPoolWorker-8] /usr/local/lib/python3.8/dist-packages/celery/app/trace.py:568: RuntimeWarning: Exception raised outside body: ModuleNotFoundError("No module named 'MySQLdb'"):
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/dist-packages/celery/backends/database/session.py", line 37, in get_engine
    return self._engines[dburi]
KeyError: 'mysql://id:pass@127.0.0.1/fundedv2'
...

해결

해결방법은 아래에서 찾을 수 있다. 간략하게 이야기를 하면, pymysql 를 설치하고, 이 PyMySQLMySQLdb 인 것처럼 인식하게 하면 된다.
그래서 pymysql 을 설치하고
pip3 install pymysql
 
project source에서 가장 top level file __init__.py에 아래 code 를 넣어주면 된다.
import pymysql
pymysql.install_as_MySQLdb()


[컴] RabbitMQ temporary queue

queue / 임시큐 / 송수신 다른 큐/ queue /

RabbitMQ temporary queue

아래처럼 임시 queue 를 만들 수 있다.
result = channel.queue_declare(queue='', exclusive=True)

한명 접속 후 삭제

exclusive=True 주면, cosumer 의 connection 이 close 되면, queue 가 삭제된다.(참고:Queues — RabbitMQ)

example

"""
                                  to_b_rk     +-----------------+
                                              |                 |
+--------+                          +------>  |     to_b_q      |          +---------+
|        |                          |         |                 +--------> |         |
|        |                          |         +-----------------+          |         |
|        |       +----------+       |                                      |         |
|    A   +-----> | to_b     |       |                                      |   B     |
|        |       |          +-------+                                      |         |
|        |       +----------+                                              |         |
|        |       +----------+                 +------------------+         |         |
+----+---+       | to_a     |                 |                  |         |         |
     ^      +--> |          +---------------->+ <random_name>    +-----+   +---+-----+
     |      |    +----------+                 | temporary queue  |     |       |
     |      |                  <random_name>  +------------------+     |       |
     |      |                                                          |       |
     |      |                                                          |       |
     |      |                                                          |       |
     |      +------------------------------------------------------------------+
     |                                                                 |
     |                                                                 |
     +-----------------------------------------------------------------+


"""

parameters = pika.URLParameters('amqp://guest:guest@127.0.0.1:5672/%2F')
connection = pika.BlockingConnection(parameters)
channel = connection.channel()

to_a = 'to_a'
to_b = 'to_b'
to_b_q = 'to_b_q'
to_b_rk = 'to_b_rk'

# to_b queue
channel.exchange_declare(exchange=to_b,
                         exchange_type='direct')
channel.queue_declare(queue=to_b_q)  # idempotent
channel.queue_bind(exchange=to_b,
                   queue=to_b_q,
                   routing_key=to_b_rk)

# to_a queue, random temporary queue
channel.exchange_declare(exchange='to_a',
                         exchange_type='direct')
result = channel.queue_declare(queue='', exclusive=True)
recv_queue = result.method.queue
channel.queue_bind(exchange='to_a',
                   queue=recv_queue,
                   routing_key=recv_queue)

# send message to to_b queue
data = {}
data['to_a_queue'] = recv_queue
message = json.dumps(data)
channel.basic_publish(exchange=to_b,
                      routing_key=to_b_rk,
                      body=message)

See Also

  1. 쿠...sal: [컴] RabbitMQ 자료들

[컴][파이썬] formatter Black

pep / formatter / python pretty formatter / yapf

Black

CPython 을 만드는 python 조직에서 만들었다.

installation

pip3 install balck

run

black ~/p/prog.py

The Black code style

black 이 code 를 어떤 스타일로 바꾸는지 알 수 있다. 이 글 에 따르면, 기존의 다른 formatter 와는 다르게 black 은 스타일을 자기가 원하는대로 변경할 수 없다고 한다.

pyproject.toml Black configuration file

기본적으로 설정파일을 사용할 필요는 없다. 다만 --include , --exclude 등을 이용해서 원하지 않은 패턴등을 추가하거나, 뺄 수 있다.
[tool.black]
line-length = 88
--verbose 를 이용하면, 어느 .toml 을 사용하는지 확인할 수 있다.
black --verbose  ~/a/prog/python/gigas/gigas/lib/net.py

pyproject.toml

pyproject.toml 은 python project 의 build system requirements 를 저장하기 위한 configuration file 이다.

pre-commit

git 에 commit 하기 전에 black 을 한번 실행하게 할 수 있다. 자세한 내용은 아래 링크를 참고하자.

[컴][유틸] 수식 그려주는 도구

수식 / 수학 식 / 공식 / 수학 기호 그려주는


수식 그려주는 도구

[컴] Github Workflow

깃허브 / 깃헙 / 워크플로우 / 액션 /유틸 / 툴 / tools / tool / util

Github Workflow

on

event 가 발생할 때마다 workflow 를 동작하게 할 수 있다. 자세한 내용은 다음 링크들을 참고하자.
# push 가 발생하면 workflow 가 동작하게 된다.
on: push
# master 에 대한 event 가 발생했을 때 동작
on:
  # Trigger the workflow on push or pull request,
  # but only for the master branch
  push:
    branches:
      - master
  pull_request:
    branches:
      - master

Reference

  1. Configuring a workflow - GitHub Help

[컴][유틸] Mermaid - markdown 형식으로 diagram 을 그릴 수 있다.

글로 그림 / 차트 그리기 / chart / draw chart / 챠트 / diagram / 다이어그램 / visio 대안

Mermaid

markdown 같은 형식으로 flow chart 를 그릴 수 있다.
vscode 에서 plugin 을 지원한다.

현재 지원하는 Diagrams

  • Flowchart
  • Sequence diagram
  • Class Diagram
  • State Diagram
  • Entity Relationship Diagram
  • User Journey
  • Gantt
  • Pie Chart

[컴][웹] firefox 에서 보안설정 간편하게 하기

firefox 보안 / 파폭 설치 후  / 파이어폭스

firefox 에서 보안설정 간편하게 하기

user.js 를 이용해서 설정을 간단하게 할 수 있다.

user.js

주의할 점은 user.js 에 설정된 값은 firefox 내에서 수정해도, firefox 를 껐다켜면 다시 값을 user.js 로 복구시킨다.
  • profile folder:
    • Windows: %APPDATA%\Mozilla\Firefox\Profiles\
    • Linux: /home/<USRNAME>/.mozilla/random.default.
    • Android: /data/data/org.mozilla.firefox/files/mozilla/xxxxxxxx.default/
  • profile folder 에 user.js 를 copy 해 놓으면 된다. 그러면 firefox 가 시작할 때 user.js 의 내용을 prefs.js 로 내용을 copy 한다.(참고: User.js file - MozillaZine Knowledge Base)
  • backup : 혹시 모르니 prefs.js 를 backup 해 놓자.
  • firefox 를 닫고 나서 작업을 하고 다시 켜자.(android 에서는 '강제종료'를 하고 하자.)

example

아래 예제는 ref.2 에서 가져와서, 몇개를 수정했다.
// Heimdallr -- Added -- Privacy Enhanced
// Disable Telemetry
user_pref("browser.urlbar.trimURLs","false");  
user_pref("browser.newtabpage.activity-stream.feeds.telemetry","false");
user_pref("browser.newtabpage.activity-stream.telemetry","false");
user_pref("browser.pingcentre.telemetry","false");
user_pref("devtools.onboarding.telemetry-logged","false");
user_pref("media.wmf.deblacklisting-for-telemetry-in-gpu-process","false");
user_pref("toolkit.telemetry.archive.enabled","false");
user_pref("toolkit.telemetry.bhrping.enabled","false");
user_pref("toolkit.telemetry.firstshutdownping.enabled","false");
user_pref("toolkit.telemetry.hybridcontent.enabled","false");
user_pref("toolkit.telemetry.newprofileping.enabled","false");
user_pref("toolkit.telemetry.unified","false");
user_pref("toolkit.telemetry.updateping.enabled","false");
user_pref("toolkit.telemetry.shutdownpingsender.enabled","false");

// Disable Plugin Scanning
user_pref("plugin.scan.plid.all","false");

// Disable Geolocation
user_pref("geo.enabled","false");

// Disable all disk caching PERIOD
user_pref("browser.cache.disk.enable","false");
user_pref("browser.cache.disk_cache_ssl","false");
user_pref("browser.cache.memory.enable","false");
user_pref("browser.cache.offline.enable","false");
user_pref("browser.cache.insecure.enable","false");

// Disable formfill
user_pref("browser.formfill.enable","false");

// Disable Zero Round Trip Time Resumption
user_pref("security.tls.enable_0rtt_data","false");

// Use only TLS 1.2 and 1.3
user_pref("security.tls.version.min","3");

// Disable Triple DES cipher
user_pref("security.ssl3.rsa_des_ede3_sha","false");

// Use strongest cipher
user_pref("security.ssl3.dhe_rsa_aes_128_sha", false);
user_pref("security.ssl3.ecdhe_ecdsa_aes_128_gcm_sha256", false);
user_pref("security.ssl3.ecdhe_ecdsa_aes_128_sha", false);
user_pref("security.ssl3.ecdhe_rsa_aes_128_gcm_sha256", false);
user_pref("security.ssl3.ecdhe_rsa_aes_128_sha", false);
user_pref("security.ssl3.rsa_aes_128_sha", false);

// Evade Finger printing
user_pref("privacy.resistfingerprinting","true");

// Disable the HORRIBLE webRTC
user_pref("media.peerconnection.enabled","false");

// Disable Prefetching
user_pref("network.dns.disablePrefetch","true");
user_pref("network.prefetch-next","false");

// Disable Referrer Headers (WHY is this is a thing)
user_pref("network.http.sendRefererHeader","0");

// Disable direct GPU access (WEBGL)
user_pref("webgl.disabled","true");

// Disable battery life check
user_pref("dom.battery.enabled","false");

// Disable session identifier
user_pref("security.ssl.disable_session_identifiers","true")

// Make requests only to site being visited
user_pref("privacy.firstparty.isolate","true")

// Disable auth fast starts 
user_pref("security.ssl.enable_false_start","false")

// Disable new tab privacy concerns
user_pref("accessibility.force_disabled", 1);
user_pref("browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons", false);
user_pref("browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features", false);
user_pref("browser.newtabpage.activity-stream.feeds.section.highlights", false);
user_pref("browser.newtabpage.activity-stream.feeds.section.topstories", false);
user_pref("browser.newtabpage.activity-stream.feeds.section.topstories.rec.impressions", "{\"50465\":1576448311544,\"50504\":1576448311544,\"50513\":1576448311544}");
user_pref("browser.newtabpage.activity-stream.feeds.section.topstories.spoc.impressions", "{\"2323\":[1576448311615,1576448311641,1576448317243]}");
user_pref("browser.newtabpage.activity-stream.feeds.snippets", false);
user_pref("browser.newtabpage.activity-stream.feeds.telemetry", false);
user_pref("browser.newtabpage.activity-stream.feeds.topsites", false);
user_pref("browser.newtabpage.activity-stream.impressionId", "{bc349b2a-4696-4afa-bf4f-48d1fd919fe0}");
user_pref("browser.newtabpage.activity-stream.improvesearch.topSiteSearchShortcuts.havePinned", "google,amazon");
user_pref("browser.newtabpage.activity-stream.prerender", false);
user_pref("browser.newtabpage.activity-stream.section.highlights.includeBookmarks", false);
user_pref("browser.newtabpage.activity-stream.section.highlights.includeDownloads", false);
user_pref("browser.newtabpage.activity-stream.section.highlights.includePocket", false);
user_pref("browser.newtabpage.activity-stream.section.highlights.includeVisited", false);
user_pref("browser.newtabpage.activity-stream.showSearch", false);
user_pref("browser.newtabpage.activity-stream.showSponsored", false);
user_pref("browser.newtabpage.enabled", false);
user_pref("browser.newtabpage.storageVersion", 1);

// Disable spell check and enable clear on shutdown
user_pref("layout.spellcheckDefault", 0);
user_pref("network.cookie.cookieBehavior", 4);
user_pref("network.cookie.lifetimePolicy", 2);
user_pref("network.http.speculative-parallel-limit", 0);
user_pref("network.trr.mode", 2);
user_pref("pdfjs.enabledCache.state", true);
user_pref("pdfjs.migrationVersion", 2);

// Correct Permissions
user_pref("permissions.default.camera", 2);
user_pref("permissions.default.desktop-notification", 2);
user_pref("permissions.default.geo", 2);
user_pref("permissions.default.microphone", 2);

// Enable privacy sanitization and disable PDF full page
user_pref("plugin.disable_full_page_plugin_for_types", "application/pdf");
user_pref("pref.privacy.disable_button.cookie_exceptions", false);
user_pref("privacy.clearOnShutdown.downloads", true);
user_pref("privacy.clearOnShutdown.formdata", true);
user_pref("privacy.clearOnShutdown.history", true);
user_pref("privacy.clearOnShutdown.offlineApps", true);
user_pref("privacy.clearOnShutdown.sessions", true);
user_pref("privacy.clearOnShutdown.siteSettings", true);
user_pref("privacy.donottrackheader.enabled", true);
user_pref("privacy.history.custom", true);
user_pref("privacy.resistFingerprinting", true);
user_pref("privacy.sanitize.pending", "[]");
user_pref("privacy.sanitize.sanitizeOnShutdown", true);
user_pref("privacy.trackingprotection.cryptomining.enabled", true);
user_pref("privacy.trackingprotection.enabled", true);
user_pref("privacy.trackingprotection.fingerprinting.enabled", true);
user_pref("toolkit.telemetry.reportingpolicy.firstRun", false);
user_pref("trailhead.firstrun.didSeeAboutWelcome", true);

Reference

  1. Profiles - Where Firefox stores your bookmarks, passwords and other user data | Firefox Help
  2. Firefox Hardening Tips 2019 - Wikis & How-to Guides - Level1Techs Forums, 2019-01-18
  3. Guide: Hardening Mozilla Firefox For Privacy & Security 2016 | Cyber Security Wiki | Viking VPN Service

[컴] 알아두면 좋을 linux commands

linux commands / linux / 리눅스 커맨드

알아두면 좋을 linux commands

dpkg -l

  • 설치된 package 들 확인방법
  • Cent OS/ RedHat
    • dnf list installed
  • Debian / Ubuntu
    • dpkg -l
    • apt list --installed

dpkg-query -L python3

  • 설치된 package 의 file 들이 어디에 있는지 알 수 있다.

whereis python3

  • binary, source, manual page files 들을 찾아준다.

locate python3

  • python3 가 들어가 있는 모든 파일의 path 를 보여준다.
  • 사용하기 위해서는 sudo updatedb 가 필요하다.(참고: UPDATEDB - Linux StepByStep)
  • vi /etc/updatedb.conf 에서 PRUNEPATHS 로 원하지 않는부분에 대한 index 를 만들지 않을 수 있다.(updatedb.conf(5) - Linux man page)
  • PRUNE_BIND_MOUNTS="yes"
    PRUNENAMES=".git .bzr .hg .svn"
    PRUNEPATHS="/tmp /var/spool /media"
    PRUNEFS="NFS nfs nfs4 rpc_pipefs afs binfmt_misc proc smbfs autofs iso9660 ncpfs coda devpts ftpfs devfs mfs shfs sysfs cifs lustre_lite tmpfs usbfs udf fuse.glusterfs fuse.sshfs ecryptfs fusesmb devtmpfs"
    

which python3

  • 현재 상태에서 실행하고 있는 python3 가 어떤 path 에 있는 python3 인지 알려준다.

iptables

netstat -lntu

  • -l : listening port
  • -n : port number
  • -t : tcp port
  • -u : udp port

cat /etc/passwd

  • 등록된 모든 유저 리스트

sudo useradd -m new_user

  • 등록된 모든 유저 리스트
  • -m : home directory 를 함께 만들어 준다.

passwd new_user

  • 암호 설정

sudo userdel -r new_user

  • user 계정 삭제
  • -r : home directory 포함 삭제

usermod -d /path/to/dir username

  • user 계정, 기본 접속 directory 변경
  • home directory 은 /etc/passwd 에서 확인이 된다.

alias function alias

# python activate
function ac() { source ~/env/$1/bin/activate; }

# history 내 특정 내용 찾기
function hs() { history | grep $1; }

# wsl 등에서 사용할 때 유용, windows path 를 wsl path 로 변경
function cdw() {
  result=$(echo "$1" | sed -e 's.\\./.g' -e 's/\/wsl\$\/Ubuntu//')
  cd $result
}

# 특정 owner 를 변경 할 때
alias chuser='sudo chown user:user $1 -R'

lsb_release -a

  • linux standard base 정보
  • 배포판 버전등을 알 수 있다.

chown

  • chown -R userid directory
  • chown userid:usergroup file

groups

  • 어느 그룹에 속해있는지 알려준다.
  • groups userid
  • chgrp userid file.txt

find . -name='*filname*'

  • 현재폴더에서 recursive 하게 filename 을 찾아준다.
  • 
    function fs() { 
      key=$(echo "*$1*")
      find . -name $key
    }


my functions in .bashrc

function ac() { source ~/a/env/$1/bin/activate; }
function hs() { history | grep $1; }
function cdw() {
  result=$(echo "$1" | sed -e 's.\\./.g' -e 's/\/wsl\$\/Ubuntu//')
  cd $result
}
function fs() { 
  key=$(echo "*$1*")
  find . -name $key
}
alias chnamh='sudo chown na:na $1 -R'



[컴] 백업 방식들

백업 / 백업 방식 / 운영 노하우/

백업 종류

  • full backup: 모든 것을 백업
    • 백업 주기: 매주(또는 그 보다 긴 주기로) 실행하는 것이 보통.
  • incremental backup(증분 백업) : 변경된 것만 백업하는 것
    • 백업 주기: 증분 백업은 매일 밤
  • synthetic full backup(통합 풀 백업) : 복원은 풀 백업처럼 하지만 백업은 그렇지 않은 백업이다.

주기적으로 전체 백업을 실행하는 이유

증분 백업으로 순차적으로 백업하면, 특정부분이 지워지고, 업데이트되는 등 비효울 적이다. 그래서 적정수준까지 full backup 으로 살리고, 이 이후 부분만 incremetal backup 을 복원(retore)하면 된다.
하지만 전체 백업을 수행하면 그 서버에 상당한 부하가 간다.
백업과 복원 효율성 사이의 trade off 가 있다.

백업방식

결과적으로 file 의 저장이 어떤 방식으로 이뤄져 있느냐에 따른 분류인듯 하다.

1. Copy

  • 가장 흔한 방법
  • 각 파일을 한 매체에서 다른 매체로 간단히 복사.(최신 파일 리스트와 파일 버전을 보고)
  • 백업 중인 시스템에 아무런 영향을 미치지 않는다.
  • 이 방법은 테이프나 디스크에서 활용
  • 시간이 오래 걸린다.

2. Block level incremental backup Snapshot

  • 디스크에서만 가능
  • 백업 시스템이 변경된 각 파일이나 블록을 스토리지 시스템에 별도의 개체로 저장하는 경우에만 가능한 방법
  • 백업 시스템이 전통적으로 백업본을 저장하던 방식, 즉, 여러 파일을 컨테이너 내부에 넣는(예: tar형식 또는 상용 백업 형식)과는 대비된다.
  • 전체 백업본을 각 object 에 대한 최신버전들의 모음(gathering) 으로 만들수 있다.(snapshot)
  • 데이터의 이동이 없기 때문에 통합 풀 백업본을 만드는 시간이 거의 걸리지 않는다. 그래서 훨씬 더 자주 만들 수 있다.
  • 실제로 이 방식을 지원하는 시스템은 대부분은 특정 파일이나 object 가 백업이 되면, 자동으로 '전체 백업본'을 만든다.
    • 블록 수준 증분 영구 백업 시스템(block-level incremental permanent backup system, block-level backup)
    • 전체 백업본을 만들어야 할 일이 없다.

3. virtual full backup

Reference

  1. 복원과 백업을 모두 효율적으로··· ‘통합 풀 백업’이란? - CIO Korea, 2020-05-15

[컴][HW] 미니 pc


mini pc / 저렴한 pc / 가벼운 / 작은 pc / 부피가 작은 / 가정용 / 애플 미니 / 집에서 / 조립용 / 미니 itx /

미니 PC

  • 베어본(ex: AsRock DeskMini)
  • 사이즈: MiniITX
  • Power: 120W 19V, 외부 전원 adapter
  • CPU : AsRock 은 i7 까지도 지원, AMD 용도 나왔다.
  • RAM : 노트북용 RAM
  • SSD : 2개까지 설치가 가능하다.
  • 다나와 '미니PC' : http://prod.danawa.com/list/?cate=112766
  • 가격
    • cpu 를 따로 설치해야 하는 '베어본' 형태는 10~20만원
    • 셀러론을 달고 나온 mini pc 는 대략 20~30만원 선

[컴] Visual Test Automation Tool - SikuliX

비쥬얼 오토메이션 툴 / 그래픽 테스트 / ui test / graphical test tool / visual test automation / 툴 / 도구 / 셀레니엄 / selenium / 연동 / 웹 자동화 테스트 / 이미지 비교 / 이미지 확인 체크 / 테스트

Visual Test Automation Tool

Commercial Tools

  • Applitools Eyes
  • Screener.io
  • Percy.io

Open source tools

  • PhantomCSS
  • WebdriverCSS
  • Huxley
  • Wraith
  • Shoov
  • Gemini
  • Galen Framework
  • SikuliX

SikuliX

SikuliX IDE 실행

java -jar sikulixide-2.0.4.jar
IDE 실행을 하면, Jython 이나 JRuby 를 설치해야 모든 기능을 할 수 있다고 나온다. 아래 page 를 참고하면 JPython 을 설치할 수 있다. 그냥 sikulixide-2.0.4.jar 와 같은 path 에 jar 을 넣어놓으면 된다.

console 에 log 를 같이 찍으려 할 때

java -jar sikulixide-2.0.4.jar -d 3 -c
-c : IDE message 영역에 있는 내용을 command line output 으로 보내준다.
-d 3 : debug level 을 set

command line option 설명

Hello World

Window10 에서 SikulX v2.0.4 로 tutorial 을 해봤지만 제대로 동작하지 않는다.

See Also

Reference

  1. Sikuli Tutorial: Automate Desktop & Windows Application With Selenium Integration | Inviul

[컴] 3D 모델링 관련 sites


3d modelling / 3d printer / 3d 프린터 /

3D 모델링 관련 sites

[컴][폰] tfp0 patch


tfp0 patch 가 뭐지? patch 

tfp0 patch

task_for_pid

XNU 커널에서 task_for_pid는 privileged process가 동일한 host에 있는 다른 process의 task port를 가져 오도록하는 기능.

  • 커널 task (프로세스 ID 0)는 가져올 수 없다.

tfp0 패치

tfp0 패치 (또는 task_for_pid (0) 패치)는 이 제한(kernel task 를 가져올 수 없는 제한)을 제거한다.

  • 그래서 "root로 실행중인 모든 실행 파일"이 pid 0 (따라서 이름)에 대해 task_for_pid를 호출 하고, vm_read 및 vm_write를 사용하여 커널 VM 영역을 수정하는 것이 가능해 진다.
  • AMFI(AppleMobileFileIntegrity - The iPhone Wiki)를 만족 시키려면 get-task-allow 자격과 task_for_pid-allow 자격(entitlement)이 필요.

Reference

[컴][폰] 안드로이드 벤치마크 사이트


android benchmark test / benchmark site / 벤치마크 사이트 / 안드로이드 폰 비교 사이트 / 비교 분석 / 어느폰이 / 가성비 / 더 좋은 핸드폰 / 스마트폰 / 필터 / 필터링

안드로이드 벤치마크 사이트

  1. Android Benchmarks - Geekbench Browser : 리스트에 cpu 가 바로 보인다.
  2. PassMark Android Benchmark Charts
  3. Ranking - AnTuTu Benchmark - Know Your Android Better
  4. Cheap smartphone price comparison : 가격까지 filtering 이 가능하다.

[컴] vscode April 2020 (version 1.45) 에서 알게된 사실

유용한 vscode extension / 확장 / plugin / 플러그인 / vscode tips / vscode 팁들 / 코드 / vs코드 / 활용법 / github 이슈 관리 쉽게 / issue 관리 / issue 분리 방법 / github 와 vscode /

vscode April 2020 (version 1.45) 에서 알게된 사실



GitHub Pull Requests and Issues extension

그림에서 '2' 번 화살표를 누르면, branch 를 만들어 준다. 그리고 그 branch 를 사용중이면 '1' 처럼 'check' 표시가 보인다. 'master' branch 로 돌아오면 사라진다.(참고로 다른 branch 로 가면 사라지지 않는다.)

그리고 code 작성 완료후 'create pull request' 를 할 수 있다.

settings.json

  • githubIssues.useBranchForIssues 가 'on' 이면, 기본적으로 githubIssues.workingIssueBranch 로 branch 를 생성한다. 그래서 prompt 를 해주면 자신이 원하는 이름으로 branch 를 생성할 수 있다.
  • githubIssues.queries: 원하는 형태로 정렬해서 list 와 대략적인 내역을 확인할 수 있다.
"githubIssues.queries": [
    {
        "label": "My Issues",
        "query": "author:${user} state:open"
    },
    {
        "label": "Created Issues",
        "query": "author:${user} state:open repo:${owner}/${repository} sort:updated-desc"
    }
],
"githubIssues.useBranchForIssues": "prompt", // on
"githubIssues.workingIssueBranch": "feature/issue${issueNumber}",
"githubPullRequests.telemetry.enabled": false,


githubIssues.createIssueTriggers

editor 에서 TODO 등을 치면 아래처럼 github issue 를 생성하는 메뉴가 보인다.




[컴] nodejs 에서 pdf 생성 및 download

client 에서 download 하기 / ajax 로 다운로드하는 방법 / download with ajax / node js download file 하는 방법

nodejs 에서 pdf 생성 및 download

pdfkit 사용법

doc.end() callback

기본적으로 doc.end() 가 되었다고 writeStream 이 끝나지 않는다. 그래서 on('close', callback) 관련 코드를 작성해줄 필요가 있다.

  async generate(data) {
    
    const that = this;
    const promise = new Promise((resolve, reject) => {
      // ref: https://github.com/foliojs/pdfkit/issues/265#issuecomment-246564718

      // To determine when the PDF has finished being written successfully 
      // we need to confirm the following 2 conditions:
      //
      //   1. The write stream has been closed
      //   2. PDFDocument.end() was called syncronously without an error being thrown

      let callCount = 2;
      const onClose = () => {
        callCount--;
        if (callCount === 0) {
          resolve();
        }
      }
      const onError = (e) => {
        reject(e);
      }

      // Pipe its output somewhere, like to a file or HTTP response
      // See below for browser usage
      const { writeStream, outFilePath } = that._createWriteStream();

      that.outFilePath = outFilePath;

      writeStream.on('close', onClose);
      writeStream.on('error', onError);

      const doc = new PDFDocument({
        size: [595, 842], // A4, 72dpi
      });;

      doc.pipe(writeStream);

      ...

      // Finalize PDF file
      doc.end();
      onClose();

      return;
    });

    const res = await promise;
    return res;
  }

ajax download

server side with andonijs

async genR2RPdf({ request, auth, response }) {
  ...
  
  try {
    
    ...
    const pgen = new MyPdfGen();
    await pgen.generate(data);
    const filepath = pgen.getOutFilePath(data);
    
    return response.attachment(filepath, `${inputData.ym}_cfstyle.pdf`);
    // return response.download(filepath); <--- 이것을 사용해도 된다.
  } catch (e) {
    Logger.error(e.stack);
    return response.status(400).json({ error: 'run_error', errors: e.message });
  }
}

client side

import 
 from 'axios';

class DownloadButton extends React.Component {
  ...
  _onClickR2rDownload(e) {
    // pdfgen
    const token = localStorage.getItem('ft');
    const auth = `Bearer ${token}`;
    const config = {
      headers: { 'Content-type': 'application/json', Authorization: auth },
      responseType: 'blob',
    };

    const fileLink = this.downloadEl;
    return axios.get(`/my/pdfgen?user_id=10`, config)
      .then((res) => {
        if (res.constructor === Error) {
          throw res;
        }
        if (res.status === 200) {
          const fileURL = window.URL.createObjectURL(new Blob([res.data]));
          fileLink.href = fileURL;
          fileLink.setAttribute('download', 'file.pdf');
          fileLink.click();
        }
      }).catch((error) => {
        console.error('Error during service worker registration:', error);
      });
  }

  render(){
    return(
        <div>
          <a ref={(el) => { this.downloadEl = el; }} />
          <button type="button" onClick={this.onClickDownload}>
            다운로드
          </button>
        </div>
    )
  }
}

[컴][네트워크] 라우팅 프로토콜

routing protocol / router / 라우팅 프로토콜  / 어떻게 패킷이 가는가 / 네트워크 알고리즘


라우팅 프로토콜

routing protocol은 3가지 형식으로 분류할 수 있다.
  1. routing table 을 누가 만드느냐에 따라 분류
  2. 내부 network에서 routing을 담당하느냐에 따른 분류
  3. routing table을 어떻게 만드느냐에 따른 분류

routing table 을 누가 만드느냐에 따라 분류

스태틱 라우팅 프로토콜(static routing protocol)

  • 사람이 직접 손으로 routing table(라우팅 테이블)을 만드는 것이다.
  • 경로에 문제가 발생하면, 다시 사람이 고쳐주지 않는 한 문제를 해결하지 못한다.

다이나믹 라우팅 프로토콜(dynamic routing protocol)

  • 라우터가 알아서 routing table을 만들어 준다.
  • 경로 이상 시 알아서 다른 경로를 설정할 수 있다.
  • 하지만 라우터의 부담이 가중된다.
  • RIP, IGRP, OSPF, EIGRP 등이 있다.

내부 network에서 routing 을 담당하느냐에 따라

  • IGP(Interior Gateway Protocol)
  • EGP(Exterior Gateway Protocol) 로 나눌 수 있다.
같은 관리자의 관리 하에 있는 라우터의 집합을 AS(Autonomous System)라고 하는데,
Autonomous System 내에서 사용되는 router 의 protocol 이 IGP이다. RIP, IGRP, EIGRP, OSPF 이 여기에 속한다.
그리고 AS와 다른 AS 사이에서 사용되는 router의 protocol이 EGP이다. BGP, EGP 이 여기에 속한다.


routing table을 어떻게 관리하는 가에 따라

  • 디스턴스 벡터 알고리즘(Distance Vector Algorithm)을 사용하는 프로토콜,
  • 링크 스테이트 알고리즘(Ling State Algorithm)을 사용하는 프로토콜
DVA 는 routing table 에 목적지까지 가는데 필요한 거리와 방향만을 기록. RIP와 IGRP가 대표적이다
LSA 는 라우터가 목적지까지 가는 경로를 SPF(Shortest-Path-First) 알고리즘이란 것을 통해 routing table에 기록. OSPF가 대표적이다.



[컴][네트워크] 인터넷 속도 측정하는 사이트

internet speed measurement / 인터넷 속도 / 스피드 측정 방법 / 측정 사이트 / 속도 확인 방법


인터넷 속도 측정하는 사이트

둘의 측정방식이 어떤 차이를 가지는지는 모르지만, 두 사이트의 값은 다르게 나온다.

[컴] ARM 의 license

Apple 의 CPU(A4, A5, A6 …) / Qualcomm 의 Snapdragon / 삼성의 Exynsos / 애플의 cpu 와 삼성의 cpu 의 차이 / 삼성의 비메모리 반도체 수준


qualcomm 의 snapdragon 이나 삼성의 엑시노스(Exynose) 와 차이가 궁금해서 조금 찾아봤다.

여기서 말하고자 하는 결론은 "Microarchitecture" 의 차이가 있다." 이다.

퀄컴도 삼성도, 그리고 애플도 전부 ARM core 를 사용한다. 처음 생각에는 이 ARM core 를 license 하는 거면, 결국 그냥 설계도 license 해서 fab(공장) 에 의뢰해서 찍어내면, core 는 다 비슷한 것 아닌가 라고 생각했다. 물론 SoC 이기 때문에 안에 들어가는 녀석들에 대한 디자인이나, 다른 core(GPU 같은) 들이 다른 성능을 가지기 때문에 그 부분이 다른 것이라고 생각했다.

ARM 의 license

그런데, 잘 못 알고 있었다. 알고 보니, ARM license 가 아래와 같이 2가지가 있다[ref. 1].
  • processor core license : Cortex A8, A9, A15…
  • ARM instruction set architecture license : ARMv7 ISA
core license 를 가진 경우에는 그냥 찍어내면 되는 것이고, instruction set architecture(ISA) 이 관한 license 가 있는 경우에는 ARM instruction set 을 기반으로 자신들이 알아서 원하는 대로 구현을 하는 것이다.

license a specific processor core (e.g. Cortex A8, A9, A15)

  • Some Qualcomm SoCs (e.g. the MSM8x25/Snapdragon S4 Play uses ARM Cortex A5s)
  • Apple A5 : Cortex-A9
  • Apple A4 : Cortex-A8
  • Samsung : Exynose seriese

license an ARM instruction set architecture (e.g. ARMv7 ISA)

  • Qualcomm Scorpion/Krait
  • Apple A6 : Swift; ARMv7-A compatible

Arm Flexible Access for Startups

ARM 이 2020년 4월30일에 발표한 새로운 라이센스 정책이다.[ref.8]

새로운 정책은 처음(early-stage, $500만 달러이하 펀딩을 받은 스타트업) 에는 돈을 안내고, 그들이 상업적인 실리콘과 비지니스 규모가 되면 그때 돈을 받는 구조이다.


A6, Exynos, Snapdragon

Apple 이나 Qualcomm 은 이 두 가지 license 를 모두 갖고 있는 듯 하다.[ref. 1]

여하튼 그래서 Apple 은 A6 부터 자신만의 CPU 를 design 해서 만들기 시작한 듯 하고[ref. 1], Qualcomm 은 Scorpion 이라고 불리는 시점부터 아니면 그 이전부터 자신들이 직접 core 를 디자인 한 듯 하다.

삼성의 Exynos 는 아직 그런 수준에 이르지는 못한 것으로 보인다. 적어도 지금까지 나온 Exynos 의 사양을 보면 ARM processor core 를 license 해서 그대로 쓰고 있는 듯 보인다.[ref. 6] ref.7 을 보면 이제 더이상 core 개발을 하지 않는다고 한다.

물론 직접 디자인 한 것이 꼭 좋다고는 할 수 없겠으나, ARM 쪽에서 특정 vendor 만을 위한 core design 을 해 줄 까닭이 없기 때문에 아무래도 이런 능력을 가지고 있으며, 자신의 제품을 만들고 있는 Apple 쪽의 전망이 유망해 보이기는 한다.

References

  1. The iPhone 5's A6 SoC: Not A15 or A9, a Custom Apple Core Instead, 2012. 9월. 15
  2. Difference Between Apple A5 and Qualcomm Snapdragon S3, 2011.11월. 13
  3. http://en.wikipedia.org/wiki/Apple_A4
  4. http://en.wikipedia.org/wiki/Apple_A5
  5. http://en.wikipedia.org/wiki/Apple_A6
  6. http://en.wikipedia.org/wiki/Exynos_(system_on_chip)
  7. 삼성전자, 자체 CPU 코어 개발 중단…"NPU·GPU에 역량 집중" - 전자신문
  8. Arm Offers Startups Zero-cost Access to its IP Portfolio | TechPowerUp, 2020-04-30