<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>끄적 끄적 로깅! 로깅!</title>
    <link>https://warpmemory.tistory.com/</link>
    <description>1. 가치있는 데이터 로깅
2. 소통과 정보 공유
3. 포트폴리오 관리
4. 스토리텔링</description>
    <language>ko</language>
    <pubDate>Sat, 27 Jun 2026 17:28:57 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>warpmemory</managingEditor>
    <image>
      <title>끄적 끄적 로깅! 로깅!</title>
      <url>https://t1.daumcdn.net/cfile/tistory/26421F4E525DF94B26</url>
      <link>https://warpmemory.tistory.com</link>
    </image>
    <item>
      <title>rsync 백업 중 메모리 사용률 급증, 원인은 두 가지: dirty page와 page cache</title>
      <link>https://warpmemory.tistory.com/175</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;리눅스 서버에서 rsync 기반 백업이 도는 시간대에 메모리 사용률이 90%를 넘기며 알람이 뜨는 상황을 겪었다. 원인을 파고들어 보니 서로 다른 두 가지가 얽혀 있었다. 하나는 &lt;b&gt;dirty page 적체&lt;/b&gt;, 다른 하나는 &lt;b&gt;rsync가 만들어내는 page cache&lt;/b&gt;다. 둘 다 &quot;메모리 사용률 증가&quot;로 보이지만 성격과 대응법이 완전히 다르다. 나중에 또 만날 것 같아 정리해 둔다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. dirty page 적체로 인한 메모리 스파이크&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;증상&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대량 파일 쓰기(백업, 미러링 등)가 일어나는 동안 메모리 사용률이 출렁이며 치솟는다. 쓰기가 일정 구간 누적되었다가 한 번에 디스크로 flush될 때 스파이크가 발생한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dirty page는 아직 디스크에 반영되지 않은, 메모리에만 존재하는 수정된 페이지다. 커널은 &lt;code&gt;vm.dirty_ratio&lt;/code&gt; / &lt;code&gt;vm.dirty_background_ratio&lt;/code&gt; 값에 따라 얼마나 쌓였을 때 flush를 시작할지 결정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함정은 일부 튜닝 프로파일에 있었다. 성능 지향 프로파일(예: &lt;code&gt;throughput-performance&lt;/code&gt;)을 적용하면 &lt;code&gt;vm.dirty_ratio&lt;/code&gt;가 기본 20%가 아니라 &lt;b&gt;40%로 올라간다.&lt;/b&gt; 즉 메모리의 40%까지 dirty page가 쌓이도록 허용되고, 그만큼 적체 후 일괄 flush 시 사용률 스파이크가 커진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주의할 점은 이 값이 &lt;code&gt;/etc/sysctl.conf&lt;/code&gt; 같은 파일에는 &lt;b&gt;드러나 있지 않다&lt;/b&gt;는 것이다. 프로파일이 런타임에 덮어쓰기 때문에, sysctl 파일만 봐서는 왜 40%인지 알 수 없다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;현재 값 확인&lt;/h3&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;sysctl vm.dirty_ratio vm.dirty_background_ratio
# 적용 중인 튜닝 프로파일 확인
tuned-adm active&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결: 프로파일 통째로 바꾸지 말고 dirty 값만 오버라이드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성능 프로파일의 다른 이점은 유지하면서 dirty 관련 값만 낮추는 게 핵심이다. 커스텀 프로파일을 만들어 기존 프로파일을 include한 뒤 dirty 값만 덮어쓴다.&lt;/p&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;mkdir -p /etc/tuned/custom-profile&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;/etc/tuned/custom-profile/tuned.conf&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;[main]
include=throughput-performance

[sysctl]
vm.dirty_ratio=20
vm.dirty_background_ratio=5&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;tuned-adm profile custom-profile
sysctl vm.dirty_ratio vm.dirty_background_ratio   # 20 / 5 확인&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리가 매우 큰 장비라면 비율(%) 대신 절대량으로 상한을 거는 방식이 더 예측 가능하다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;[sysctl]
vm.dirty_bytes=1073741824          # 1GB
vm.dirty_background_bytes=268435456 # 256MB&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(주의: &lt;code&gt;dirty_bytes&lt;/code&gt;를 설정하면 &lt;code&gt;dirty_ratio&lt;/code&gt;는 0으로 무시된다. 둘 중 하나만 쓴다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 한 가지 조정만으로 적체 후 일괄 flush로 인한 스파이크는 눈에 띄게 완화된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. rsync가 쌓는 page cache&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;증상&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dirty 값을 조정했는데도 백업이 끝나갈 무렵 메모리 사용률이 높게 유지된다. 그런데 이건 성격이 다르다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;rsync는 읽고 쓰는 파일을 page cache에 올린다. 백업처럼 한 번 읽고 다시 안 쓸 데이터까지 캐시에 차곡차곡 쌓이면서 &lt;code&gt;buff/cache&lt;/code&gt;가 부풀어 오른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 사실 &lt;b&gt;문제가 아닌 정상 동작&lt;/b&gt;이다. page cache는 reclaimable이라 다른 프로세스가 메모리를 필요로 하면 커널이 알아서 회수한다. &lt;code&gt;free -m&lt;/code&gt;에서 &lt;code&gt;available&lt;/code&gt; 값이 충분하면 실제로는 여유가 있는 상태다.&lt;/p&gt;
&lt;pre class=&quot;vala&quot;&gt;&lt;code&gt;free -m
# total used free shared buff/cache available
# used가 아니라 available을 봐야 한다&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 모니터링 알람이 &lt;code&gt;buff/cache&lt;/code&gt;까지 포함한 &quot;used 기준 사용률&quot;로 임계치를 잡는 경우다. 실제로는 회수 가능한데 알람만 울린다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 1: nocache로 캐시 적재 자체를 막기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일회성 백업처럼 캐시에 남길 필요가 없는 작업은 &lt;code&gt;nocache&lt;/code&gt;로 감싸면 된다. &lt;code&gt;LD_PRELOAD&lt;/code&gt;로 &lt;code&gt;open&lt;/code&gt;/&lt;code&gt;close&lt;/code&gt; 등을 후킹해서, 파일이 &lt;b&gt;닫힐 때마다&lt;/b&gt; 그 파일에 대해 &lt;code&gt;posix_fadvise(POSIX_FADV_DONTNEED)&lt;/code&gt;를 호출해 page cache에서 비운다.&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;nocache rsync -avuz /src/ /dst/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 &lt;b&gt;끝에 한 번만 비우는 게 아니라 파일 단위로 비운다&lt;/b&gt;는 점이다. rsync가 파일 하나를 다 전송하고 &lt;code&gt;close()&lt;/code&gt; 하는 순간 그 파일이 차지하던 캐시가 즉시 해제된다. 그래서 수많은 파일을 도는 장시간 동기화에서도 캐시가 끝까지 누적되지 않고 일정 수준으로 유지된다. (쓰기 파일은 DONTNEED가 dirty page를 못 비우므로 nocache가 close 시 &lt;code&gt;fdatasync&lt;/code&gt;로 먼저 flush한 뒤 비운다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;nocache&lt;/code&gt;라는 이름 때문에 &quot;캐시를 아예 못 쓰게 해서 느려지는 것 아니냐&quot;는 오해가 있는데, 그렇지 않다. &lt;b&gt;처리가 끝난 파일의 페이지를 캐시에서 비워줄 뿐&lt;/b&gt;, 다른 프로세스나 시스템 전체의 캐시 사용을 막는 게 아니다. 또 열 때 이미 캐시에 있던 페이지는 건드리지 않고 자기가 새로 올린 페이지만 골라 비운다. 단발성 백업/복사처럼 어차피 재사용 안 할 데이터엔 안성맞춤이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 약점이 하나 있다. &lt;b&gt;하나의 거대한 파일을 오래 전송하는 경우&lt;/b&gt;, 그 파일은 close될 때까지 열려 있으므로 그동안 캐시가 쌓이고 닫힐 때 한꺼번에 해제된다. 작은~중간 파일이 많은 일반적인 백업에는 잘 맞지만, &quot;수십 GB짜리 파일 하나&quot;가 메인이면 효과가 제한적일 수 있다. 이럴 땐 아래 cgroup 방식이 더 확실하다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;설치 (EPEL 또는 소스 빌드)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;nocache&lt;/code&gt;는 RHEL/Rocky/CentOS 계열 &lt;b&gt;기본 저장소에는 없다.&lt;/b&gt; EPEL에 있거나, 없으면 소스로 빌드한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EPEL이 가능하면:&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;yum install -y epel-release
yum install -y nocache&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EPEL을 못 쓰는 환경(폐쇄망 등)이면 소스 빌드가 깔끔하다. 의존성이 거의 없고 빌드도 가볍다.&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;# 빌드 도구
yum install -y git make gcc

# 소스 받아 빌드
git clone https://github.com/Feh/nocache.git
cd nocache
make
make install        # 기본 PREFIX=/usr/local &amp;rarr; /usr/local/bin/nocache

# 확인
which nocache
nocache --help&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폐쇄망이면 인터넷 되는 곳에서 tarball(또는 git clone)만 받아 반입한 뒤 &lt;code&gt;make &amp;amp;&amp;amp; make install&lt;/code&gt; 하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 같은 데이터를 반복적으로 읽어 캐시 효과가 중요한 쪽(서비스가 읽는 원본 경로 등)에는 적용하지 않는 게 좋다. 백업의 목적지(dest) 쪽이나 일회성 작업에 거는 게 안전하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 2: cgroup으로 메모리 상한 걸기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 작업이 쓸 수 있는 메모리(캐시 포함) 자체를 제한하고 싶다면 cgroup으로 스코프를 묶는다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;systemd-run --scope -p MemoryHigh=3G -p MemoryMax=4G rsync -avuz /src/ /dst/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;MemoryHigh&lt;/code&gt;를 넘으면 커널이 해당 스코프의 캐시를 적극적으로 회수하며 압박하고, &lt;code&gt;MemoryMax&lt;/code&gt;는 하드 리밋이다. 시스템 전체 메모리 사용률이 백업 때문에 튀는 걸 근본적으로 묶어둘 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;현상&lt;/th&gt;
&lt;th&gt;원인&lt;/th&gt;
&lt;th&gt;핵심 대응&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;쓰기 중 사용률 스파이크&lt;/td&gt;
&lt;td&gt;dirty page 적체 후 일괄 flush&lt;/td&gt;
&lt;td&gt;dirty_ratio 낮춤 (커스텀 tuned 프로파일)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;백업 후 사용률 높게 유지&lt;/td&gt;
&lt;td&gt;rsync page cache 누적&lt;/td&gt;
&lt;td&gt;nocache 또는 cgroup 메모리 상한&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;교훈 세 가지.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;&quot;메모리 사용률 높음&quot;을 한 덩어리로 보면 안 된다.&lt;/b&gt; dirty page(쓰기 적체)와 page cache(읽기 캐시)는 원인도 대응도 다르다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;튜닝 프로파일이 sysctl 값을 몰래 바꾼다.&lt;/b&gt; 설정 파일만 보지 말고 &lt;code&gt;tuned-adm active&lt;/code&gt;로 적용 프로파일을 확인하자. 그리고 프로파일을 통째로 갈아엎기보다 include + 필요한 값만 오버라이드하는 게 깔끔하다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;page cache 증가는 대부분 정상이다.&lt;/b&gt; &lt;code&gt;available&lt;/code&gt;을 보고 판단하고, 알람 임계치가 &lt;code&gt;buff/cache&lt;/code&gt;를 포함하는지 점검하자.&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>운영체제</category>
      <category>dirty_ratio</category>
      <category>Linux</category>
      <category>nocache</category>
      <category>Page Cache</category>
      <category>rsync</category>
      <category>tuned</category>
      <author>warpmemory</author>
      <guid isPermaLink="true">https://warpmemory.tistory.com/175</guid>
      <comments>https://warpmemory.tistory.com/175#entry175comment</comments>
      <pubDate>Fri, 26 Jun 2026 11:36:00 +0900</pubDate>
    </item>
    <item>
      <title>[linux] cron.d 설정으로 haproxy 로그 logrotate 적용</title>
      <link>https://warpmemory.tistory.com/172</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;1분 주기로 haproxy 로그 확인해서 100M 넘으면 로테이트해서 500개 까지 보관(crontab 사용하지 않고, /etc/cron.d 설정)&lt;/p&gt;
&lt;pre id=&quot;code_1697788929064&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mkdir /etc/logrotate.hourly

cat &amp;lt;&amp;lt;EOF &amp;gt; /etc/logrotate.hourly/haproxy
/var/log/haproxy/haproxy.log
/var/log/haproxy/haproxy-*.log {
  hourly
  missingok
  nocompress
  notifempty
  size 100M
  rotate 500
  dateext
  dateformat -%Y%m%d%H-%s
  #copytruncate
  postrotate
    /usr/bin/pgrep rsyslogd | xargs -I{} kill -s HUP {}
  endscript
}
EOF

mkdir /etc/cron.minutely

cat &amp;lt;&amp;lt;EOF &amp;gt; /etc/cron.minutely/0logrotate.hourly
/usr/sbin/logrotate  /etc/logrotate.hourly/haproxy
EOF

chmod 750 /etc/cron.minutely/0logrotate.hourly
 
cat &amp;lt;&amp;lt;EOF &amp;gt; /etc/cron.d/0minutely
# Run the hourly jobs
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
* * * * * root run-parts /etc/cron.minutely
EOF

chmod 640 /etc/cron.d/0minutely&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>운영체제</category>
      <category>cron.d</category>
      <category>cron.minutely</category>
      <category>Linux</category>
      <author>warpmemory</author>
      <guid isPermaLink="true">https://warpmemory.tistory.com/172</guid>
      <comments>https://warpmemory.tistory.com/172#entry172comment</comments>
      <pubDate>Fri, 20 Oct 2023 17:12:59 +0900</pubDate>
    </item>
    <item>
      <title>Linux에서 삭제된 파일 물고 있는 프로세스 찾는 방법</title>
      <link>https://warpmemory.tistory.com/171</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;lsof +L1&amp;nbsp;&lt;/p&gt;</description>
      <category>운영체제</category>
      <author>warpmemory</author>
      <guid isPermaLink="true">https://warpmemory.tistory.com/171</guid>
      <comments>https://warpmemory.tistory.com/171#entry171comment</comments>
      <pubDate>Thu, 8 Jun 2023 20:48:43 +0900</pubDate>
    </item>
    <item>
      <title>git에서 시크릿 파일 삭제 방법</title>
      <link>https://warpmemory.tistory.com/170</link>
      <description>&lt;p&gt;&lt;span&gt;시크릿 데이터가 원격 저장소에 저장되었을때 삭제 방법입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;git filter-branch --force --tree-filter 'rm -f etc/*' --prune-empty HEAD&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;git push --force origin master&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>프로그래밍</category>
      <author>warpmemory</author>
      <guid isPermaLink="true">https://warpmemory.tistory.com/170</guid>
      <comments>https://warpmemory.tistory.com/170#entry170comment</comments>
      <pubDate>Mon, 29 Mar 2021 15:39:17 +0900</pubDate>
    </item>
    <item>
      <title>Linux에서 tcpdump 시간 단위로 pcap 파일 생성</title>
      <link>https://warpmemory.tistory.com/169</link>
      <description>&lt;p&gt;tcpdump.sh 스크립트 생성&lt;/p&gt;
&lt;pre id=&quot;code_1609293227189&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#/bin/bash
export PATH=$PATH:/usr/bin:/usr/sbin
DUMP_NAME=&quot;api&quot;
DUMP_DIR=&quot;/root&quot;
DUMP_FILE=&quot;${DUMP_NAME}_%Y-%m-%d_%H:%M.pcap&quot;
find $DUMP_DIR -name &quot;${DUMP_NAME}_*.pcap&quot; -mtime +2 -delete
ps -ef |egrep &quot;tcpdump .* ${DUMP_DIR}/${DUMP_FILE}&quot; |grep -v grep |awk '{print $2}' |xargs kill -3 &amp;gt; /dev/null 2&amp;gt;&amp;amp;1
timeout 24h tcpdump -i eth0 port 80 -G 3600 -w ${DUMP_DIR}/${DUMP_FILE} &amp;gt; /dev/null 2&amp;gt;&amp;amp;1 &amp;amp;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;crontab -e 로 스케줄러 등록&lt;/p&gt;
&lt;pre id=&quot;code_1609293299175&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# restart tcpdump
0 0 * * * /root/tcpdump.sh &amp;gt; /dev/null 2&amp;gt;&amp;amp;1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>운영체제</category>
      <author>warpmemory</author>
      <guid isPermaLink="true">https://warpmemory.tistory.com/169</guid>
      <comments>https://warpmemory.tistory.com/169#entry169comment</comments>
      <pubDate>Wed, 30 Dec 2020 10:57:44 +0900</pubDate>
    </item>
    <item>
      <title>PostgreSQL 테이블 Vacuum 모니터링</title>
      <link>https://warpmemory.tistory.com/168</link>
      <description>&lt;pre id=&quot;code_1595211671621&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT datname, age(datfrozenxid) FROM pg_database ORDER BY age(datfrozenxid) desc;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1595211756647&quot; class=&quot;html xml&quot; style=&quot;display: block; overflow: auto; padding: 15px; color: #383a42; background: #f6f7f8; font-size: 14px; border-radius: 3px; font-family: Menlo, Consolas, Monaco, monospace; border: 1px solid #dddddd; margin: 20px auto 0px; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;         datname         |    age     
-------------------------+------------
 aaaaaaaaaaaaaaaa        | 1485485076
 bbbbbbbbbbbbbbbbbbbbbbb | 1481342364
 cccccccccccccccccccc    | 1461333757
 dddddddddddddddddd      | 1330037484
 postgres                | 1329674313
 fffffffff               | 1156326849
 ggggggggggggggggggggggg |  100464636
 template1               |     382402
 template0               |     378203
(9 rows)​&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;데이터베이스의 수명이 20억 트랜잭션 ID에 도달하면, 트랜잭션 ID(XID) 랩어라운드가 발생하고 데이터베이스는 읽기 전용이 됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>엔지니어링</category>
      <author>warpmemory</author>
      <guid isPermaLink="true">https://warpmemory.tistory.com/168</guid>
      <comments>https://warpmemory.tistory.com/168#entry168comment</comments>
      <pubDate>Mon, 20 Jul 2020 11:25:09 +0900</pubDate>
    </item>
    <item>
      <title>타임라인 및 검색 시스템 설계</title>
      <link>https://warpmemory.tistory.com/167</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;사전 지식&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용기술&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AWS
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Elastic Load Balancing(ELB)&lt;/li&gt;
&lt;li&gt;Elastic Computing(EC2)&lt;/li&gt;
&lt;li&gt;ElastiCache(Redis Cluster)&lt;/li&gt;
&lt;li&gt;Elasticsearch(ELK)&lt;/li&gt;
&lt;li&gt;EC2 Autoscailing&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Linux
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CentoOS&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Nginx
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UWSGI&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Python
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Django&lt;/li&gt;
&lt;li&gt;Celery&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;MySQL&lt;/li&gt;
&lt;li&gt;Kafka&lt;/li&gt;
&lt;li&gt;Storm&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;개발 사전 체크&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기획 내용의 검토&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Timeline 시나리오 설계 및 구축&lt;/span&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;특정 유저가 다른 유저 혹은 인플루언서를 팔로우할 경우 모아보기를 지원해야 함&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Only DB Query로 구축은 지양하고, 확장성 및 성능을 고려한 설계 필요(DB로 설계했을 때 방안도 고려)&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;AWS ELK를 활용한 검색 시나리오 설계 및 구축&lt;/span&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;사용자가 작성한 글/크롤링한 데이터/커뮤니티 검색 지원&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결하고자 하는 문제&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;확장성 및 성능을 고려한 Timeline 시스템 구축&lt;/li&gt;
&lt;li&gt;데이터 크롤링 및 검색 시스템 구축&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;개발 범위&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Timeline 시스템
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자가 post 시 팔로워 timeline에 post 추가&lt;/li&gt;
&lt;li&gt;Only DB Query 구축 지양, 확장성 및 성능을 만족&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Redis 클러스터를 이용한 캐시 시스템&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;검색 시스템
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;크롤링 시스템
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;URL, Keyword 등 설정에 따른 크롤링&lt;/li&gt;
&lt;li&gt;크롤링 사이트, 속도 제한&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;파이프라인 시스템
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터 버퍼링&lt;/li&gt;
&lt;li&gt;데이터 유실 없어야 하고&lt;/li&gt;
&lt;li&gt;장애 내성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;스트림 프로세싱
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파싱&lt;/li&gt;
&lt;li&gt;필터링&lt;/li&gt;
&lt;li&gt;인덱싱&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;검색 시스템
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터 저장&lt;/li&gt;
&lt;li&gt;검색&lt;/li&gt;
&lt;li&gt;검색 결과 랭크&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;통계 시스템
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인덱스 통계&lt;/li&gt;
&lt;li&gt;검색 통계&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;캐시 구축
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;검색 결과 캐시&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;API 구축&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;검색&lt;/li&gt;
&lt;li&gt;검색 결과 랭크&lt;/li&gt;
&lt;li&gt;post 등록 시 검색 인덱스 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;주요 프로세스 및 시나리오&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시스템 구성 및 프로세스&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-origin-width=&quot;0.0&quot; data-origin-height=&quot;0.0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNJD7i/btqFiOGJfvK/eWFQMGrayy883tfHbLTKw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNJD7i/btqFiOGJfvK/eWFQMGrayy883tfHbLTKw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNJD7i/btqFiOGJfvK/eWFQMGrayy883tfHbLTKw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNJD7i%2FbtqFiOGJfvK%2FeWFQMGrayy883tfHbLTKw1%2Fimg.png&quot; data-origin-width=&quot;0.0&quot; data-origin-height=&quot;0.0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심 로직&lt;/h2&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;Timeline 시스템&lt;/h3&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;MySQL 구성&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Relational Database Service(RDS)가 EC2 기반으로 서비스됨&lt;/li&gt;
&lt;li&gt;비용 측면에서 RDS 사용하지 않고, EC2에 직접 DBMS 구축해서 사용해도 됨&lt;/li&gt;
&lt;li&gt;DB 이중화 및 주기적인 백업 시스템 필수&lt;/li&gt;
&lt;li&gt;멀티 마스터 구조 또는 Master - Slaves 구성인 경우 라이브러리 단에서&amp;nbsp; Read/Write 구분하여 사용&lt;/li&gt;
&lt;li&gt;데이터가 많아지면 데이터 베이스 샤딩/파티셔닝 고려&lt;/li&gt;
&lt;li&gt;운영 이슈가 심각해지면 RDS로 이전 고려&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;MySQL 스키마&lt;/h4&gt;
&lt;pre class=&quot;n1ql&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE `user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `email` varchar(256),
  `name` varchar(256),
  `influencer` char(1) DEFAULT 'f',
  `created_at` datetime DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`),
  UNIQUE KEY `IDX_user_email` (`email`),
  KEY `IDX_user_name` (`name`),
  KEY `IDX_user_influencer` (`influencer`),
  KEY `IDX_user_created_at` (`created_at`)
) ENGINE=INNODB DEFAULT CHARSET='utf8';&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;sql&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE `follower` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(10) unsigned,
  `follower_user_id` int(10) unsigned,
  `created_at` datetime DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`),
  KEY `IDX_follower_user_id` (`user_id`),
  KEY `IDX_follower_created_at` (`created_at`),
  FOREIGN KEY (`user_id`) 
  REFERENCES user(`id`) ON UPDATE CASCADE ON DELETE RESTRICT
) ENGINE=INNODB DEFAULT CHARSET='utf8';&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;sql&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE `post` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(10) unsigned NOT NULL,
  `contents` text NOT NULL,
  `tags` text,
  `locale` varchar(256) NOT NULL DEFAULT '',
  `created_at` datetime DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`),
  KEY `IDX_post_user_id` (`user_id`),
  KEY `IDX_post_locale` (`locale`),  
  KEY `IDX_post_created_at` (`created_at`),
  FOREIGN KEY (`user_id`) 
  REFERENCES user(`id`) ON UPDATE CASCADE ON DELETE RESTRICT
) ENGINE=INNODB DEFAULT CHARSET='utf8';&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;MySQL 타임라인 조회&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자의 팔로워가 많아지면 많아질수록 부하 문제 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;n1ql&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT
    *
FROM
    post
WHERE
    user_id in (
        SELECT
            user_id
        FROM
            follower
        WHERE
            follower_user_id = {user_id}
    )
    OR user_id = {user_id}
ORDER BY created_at DESC LIMIT 20;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;MySQL 사용자가 팔로우하는 인플루언서 조회&lt;/h4&gt;
&lt;pre class=&quot;routeros&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT
    u.id, u.influencer
FROM
    follower AS f JOIN user AS u ON u.id=f.user_id
WHERE
    f.follower_user_id={user_id} AND u.influencer='t';&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;Redis 스키마&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;키 : 벨류&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;ada&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;USER_{user_id}_INFLUENCERS : Sets(1, 3, 5, 7)
USER_{user_id}_FOLLOWINGS : Sets(2, 4, 6, 8)
USER_{user_id}_POSTS : Lists[1, 2, 3, 7, 8, 9]
POST_{post_id} : Strings '{
    &quot;user_id&quot;: 1,
    &quot;user_name&quot;: &quot;사용자1&quot;,
    &quot;contents&quot;: &quot;포스트1&quot;,
    &quot;created_at&quot;: &quot;2020-07-02 10:09:10&quot;
}'&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;Redis 타임라인 조회&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Redis 클러스터에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;액티브(2주&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;안에 접속한) 사용자에 대한 타임라인을 미리 생성&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;저장하여&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;서비스&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;캐시가 없는 경우에는 MySQL에서 가져와서, 캐시 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;ttl 시간을 2주로 설정, 해당 키 접근 시 마다 ttl 시간이 2주가 되도록 설정&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인플루언서의 post가 아닌 경우는, post 등록 즉시 팔로워들의 POSTS 캐시에 바로 추가(Push 방식)&lt;/li&gt;
&lt;li&gt;인플루언서의 post인 경우는, 팔로워가 접속했을 때, 팔로워의 POSTS 캐시에&lt;span&gt;&amp;nbsp;&lt;/span&gt;인플루언서&lt;span&gt;&amp;nbsp;&lt;/span&gt;포스트를 가져와 병합(Pull 방식)&lt;/li&gt;
&lt;li&gt;MySQL과 최종 정합성 고려&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;API 서버&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;EC2로 구축
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Nginx : 웹 서버&lt;/li&gt;
&lt;li&gt;uWSGI(Web Server Gateway Interface) : Nginx서버와 Python 애플리케이션 간 통신 인터페이스 모듈&lt;/li&gt;
&lt;li&gt;Django REST framework(DRF) : Django RESTful 프레임워크&lt;/li&gt;
&lt;li&gt;REST Swagger : API 문서 자동화&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Amazon EC2 Autoscailing 사용하여, 서버 부하에 대응&lt;/li&gt;
&lt;li&gt;RESTful 조건에 만족하도록 개발&lt;/li&gt;
&lt;li&gt;GET /api/v1/posts
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;user_id&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;POST /api/v1/posts
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;user_id&lt;/li&gt;
&lt;li&gt;contents&lt;/li&gt;
&lt;li&gt;tags&lt;/li&gt;
&lt;li&gt;locale&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;Celery 서버&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비동기 태스크 큐로 post가 들어왔을 때, Redis 클러스터에 Timeline Cache 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;검색 시스템&lt;/h3&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;수집(Crawler)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;검색 대상 URL 및 검색 키워드 설정에 따라 데이터 수집&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;수집 대상 설정 가져오는 기능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;crawler 속도 제한 기능 필수&lt;/li&gt;
&lt;li&gt;robots.txt 확인하여, crawler 제한된 사이트 제외&lt;/li&gt;
&lt;li&gt;사이트 도메인별로 Kafka 토픽 데이터 저장(스트림 프로세싱 단순화)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Twitter&lt;/li&gt;
&lt;li&gt;Facebook&lt;/li&gt;
&lt;li&gt;YouTube&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;파이프라인(Kafka 클러스터)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;EC2로 Kafka 클러스터(+Zookeeper) 파이프라인 구축
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Consumer가 broker로 부터 메시지를 pull 하는 방식
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Consumer가 처리 가능할 때 메시지를 가져와 처리
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자원 효율적 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;메시지를 disk에 저장 하기 때문에 이미 처리한 큐도, 다시 가져와서 처리가 가능 함
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Consumer 장애 시에도 데이터 누락 없이 처리 할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;메시지를 쌓아 두었다가 한번에 처리하는 배치 처리도 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;클러스터로 장애 내성을 갖음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;데이터 규모에 따라서 클러스터 규모 산정
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최소 설정은 3개 클러스터에 복제 1개 이상&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;수집 데이터 보관 기간 설정(log.retention.hours=72)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;수집 용량 및 스트림 스로세싱 시스템 장애등을 고려해서 조정&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;스트림 프로세싱(Storm 클러스터)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;EC로 Storm 클러스터(+Zookeeper) 스트림 프로세싱 구성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;분산 처리 프레임워크로 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;파이프라인으로 들어온 데이터 가공
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;필터링
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중복 데이터 제거&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;파싱&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;도메인 및 데이터 타입별로 데이터 파싱&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;필터링
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중복 데이터 제거&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인덱싱/태깅
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인덱스 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;메타데이터 생성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;날자&lt;/li&gt;
&lt;li&gt;지역&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;검색 시스템(Elasticsearch 클러스터)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스트림 프로세싱으로 가공된 검색 데이터 저장
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;url&lt;/li&gt;
&lt;li&gt;title&lt;/li&gt;
&lt;li&gt;summary&lt;/li&gt;
&lt;li&gt;content_type&lt;/li&gt;
&lt;li&gt;created_at&lt;/li&gt;
&lt;li&gt;locale&lt;/li&gt;
&lt;li&gt;tags&lt;/li&gt;
&lt;li&gt;click_count&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;검색 정보 저장
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;keyword&lt;/li&gt;
&lt;li&gt;locale&lt;/li&gt;
&lt;li&gt;created_at&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Query 기능&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;통계 시스템(Kibana)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인덱스 통계 데이터 제공 및 시각화&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;캐시 시스템(Redis 클러스터)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;검색 결과를 캐시&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;API 서버&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;Timeline API 서버 구성 사용&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;Celery 서버&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비동기 태스크 큐 처리
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;검색 키워드 저장&lt;/li&gt;
&lt;li&gt;검색 결과 클릭 카운팅&lt;/li&gt;
&lt;li&gt;검색 결과 캐시 생성&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;신규 포스트 데이터 검색 시스템에 저장&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;모니터링 시스템&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;처리량 모니터링
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;부하 발생 하거나, 유입량 보다 처리량이 낮으면 노티&lt;/li&gt;
&lt;li&gt;스케일 아웃 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;에러 모니터링
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;에러 발생시 노티&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프로젝트</category>
      <author>warpmemory</author>
      <guid isPermaLink="true">https://warpmemory.tistory.com/167</guid>
      <comments>https://warpmemory.tistory.com/167#entry167comment</comments>
      <pubDate>Thu, 2 Jul 2020 14:01:24 +0900</pubDate>
    </item>
    <item>
      <title>Linux find 명령어로 날자별 디렉토리 파일 이동 및 복원</title>
      <link>https://warpmemory.tistory.com/166</link>
      <description>&lt;div class=&quot;colorscripter-code&quot; style=&quot;color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position:relative !important;overflow:auto&quot;&gt;&lt;table class=&quot;colorscripter-code-table&quot; style=&quot;margin:0;padding:0;border:none;background-color:#fafafa;border-radius:4px;&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;&lt;tr&gt;&lt;td style=&quot;padding:6px;border-right:2px solid #e5e5e5&quot;&gt;&lt;div style=&quot;margin:0;padding:0;word-break:normal;text-align:right;color:#666;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%&quot;&gt;&lt;div style=&quot;line-height:130%&quot;&gt;1&lt;/div&gt;&lt;div style=&quot;line-height:130%&quot;&gt;2&lt;/div&gt;&lt;div style=&quot;line-height:130%&quot;&gt;3&lt;/div&gt;&lt;div style=&quot;line-height:130%&quot;&gt;4&lt;/div&gt;&lt;div style=&quot;line-height:130%&quot;&gt;5&lt;/div&gt;&lt;div style=&quot;line-height:130%&quot;&gt;6&lt;/div&gt;&lt;div style=&quot;line-height:130%&quot;&gt;7&lt;/div&gt;&lt;div style=&quot;line-height:130%&quot;&gt;8&lt;/div&gt;&lt;div style=&quot;line-height:130%&quot;&gt;9&lt;/div&gt;&lt;div style=&quot;line-height:130%&quot;&gt;10&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;padding:6px 0;text-align:left&quot;&gt;&lt;div style=&quot;margin:0;padding:0;color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%&quot;&gt;&lt;div style=&quot;padding:0 6px; white-space:pre; line-height:130%&quot;&gt;&lt;span style=&quot;color:#999999&quot;&gt;#&amp;nbsp;날자별&amp;nbsp;디렉토리&amp;nbsp;이동&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;padding:0 6px; white-space:pre; line-height:130%&quot;&gt;find&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;home&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;hosting&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;webanalyzer&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;data&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;db&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;*&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;maxdepth&amp;nbsp;&lt;span style=&quot;color:#0099cc&quot;&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;type&amp;nbsp;d&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;name&amp;nbsp;&lt;span style=&quot;color:#63a35c&quot;&gt;&quot;`date&amp;nbsp;+'%Y%m'&amp;nbsp;-d&amp;nbsp;'1&amp;nbsp;year&amp;nbsp;ago&amp;nbsp;1&amp;nbsp;month&amp;nbsp;ago'`&quot;&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#066de2&quot;&gt;exec&lt;/span&gt;&amp;nbsp;bash&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;c&amp;nbsp;&lt;span style=&quot;color:#63a35c&quot;&gt;'basedir=$(dirname&amp;nbsp;{})&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;mkdir&amp;nbsp;-p&amp;nbsp;/home/_trash$basedir&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;mv&amp;nbsp;{}&amp;nbsp;/home/_trash$basedir'&lt;/span&gt;&amp;nbsp;\;&lt;/div&gt;&lt;div style=&quot;padding:0 6px; white-space:pre; line-height:130%&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;padding:0 6px; white-space:pre; line-height:130%&quot;&gt;find&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;home&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;hosting&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;webanalyzer&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;data&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;db&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;*&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;maxdepth&amp;nbsp;&lt;span style=&quot;color:#0099cc&quot;&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;type&amp;nbsp;d&amp;nbsp;\(&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;regex&amp;nbsp;&lt;span style=&quot;color:#63a35c&quot;&gt;'.*2018[01][0-9]$'&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;or&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;regex&amp;nbsp;&lt;span style=&quot;color:#63a35c&quot;&gt;'.*20190[1-5]$'&lt;/span&gt;&amp;nbsp;\)&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#066de2&quot;&gt;exec&lt;/span&gt;&amp;nbsp;bash&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;c&amp;nbsp;&lt;span style=&quot;color:#63a35c&quot;&gt;'basedir=$(dirname&amp;nbsp;{})&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;mkdir&amp;nbsp;-p&amp;nbsp;/home/_trash$basedir&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;mv&amp;nbsp;{}&amp;nbsp;/home/_trash$basedir'&lt;/span&gt;&amp;nbsp;\;&lt;/div&gt;&lt;div style=&quot;padding:0 6px; white-space:pre; line-height:130%&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;padding:0 6px; white-space:pre; line-height:130%&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;padding:0 6px; white-space:pre; line-height:130%&quot;&gt;&lt;span style=&quot;color:#999999&quot;&gt;#&amp;nbsp;이동된&amp;nbsp;디렉토리&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;padding:0 6px; white-space:pre; line-height:130%&quot;&gt;find&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;home&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;_trash&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;home&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;hosting&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;webanalyzer&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;data&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;db&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;*&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;maxdepth&amp;nbsp;&lt;span style=&quot;color:#0099cc&quot;&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;type&amp;nbsp;d&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;name&amp;nbsp;&lt;span style=&quot;color:#63a35c&quot;&gt;&quot;`date&amp;nbsp;+'%Y%m'&amp;nbsp;-d&amp;nbsp;'1&amp;nbsp;year&amp;nbsp;ago&amp;nbsp;1&amp;nbsp;month&amp;nbsp;ago'`&quot;&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#066de2&quot;&gt;exec&lt;/span&gt;&amp;nbsp;bash&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;c&amp;nbsp;&lt;span style=&quot;color:#63a35c&quot;&gt;'basedir=$(dirname&amp;nbsp;{})&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;targetdir=&quot;${basedir#/*/*/}&quot;&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;&amp;nbsp;mv&amp;nbsp;{}&amp;nbsp;/$targetdir'&lt;/span&gt;&amp;nbsp;\;&lt;/div&gt;&lt;div style=&quot;padding:0 6px; white-space:pre; line-height:130%&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;padding:0 6px; white-space:pre; line-height:130%&quot;&gt;find&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;home&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;_trash&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;home&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;hosting&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;webanalyzer&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;data&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;db&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;*&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;maxdepth&amp;nbsp;&lt;span style=&quot;color:#0099cc&quot;&gt;1&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;type&amp;nbsp;d&amp;nbsp;\(&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;regex&amp;nbsp;&lt;span style=&quot;color:#63a35c&quot;&gt;'.*2018[01][0-9]$'&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;or&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;regex&amp;nbsp;&lt;span style=&quot;color:#63a35c&quot;&gt;'.*20190[1-5]$'&lt;/span&gt;&amp;nbsp;\)&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#066de2&quot;&gt;exec&lt;/span&gt;&amp;nbsp;bash&amp;nbsp;&lt;span style=&quot;color:#0086b3&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color:#a71d5d&quot;&gt;-&lt;/span&gt;c&amp;nbsp;&lt;span style=&quot;color:#63a35c&quot;&gt;'basedir=$(dirname&amp;nbsp;{})&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;targetdir=&quot;${basedir#/*/*/}&quot;&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;&amp;nbsp;mv&amp;nbsp;{}&amp;nbsp;/$targetdir'&lt;/span&gt;&amp;nbsp;\;&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;vertical-align:bottom;padding:0 2px 4px 0&quot;&gt;&lt;a href=&quot;http://colorscripter.com/info#e&quot; target=&quot;_blank&quot; style=&quot;text-decoration:none;color:white&quot;&gt;&lt;span style=&quot;font-size:9px;word-break:normal;background-color:#e5e5e5;color:white;border-radius:10px;padding:1px&quot;&gt;cs&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;</description>
      <category>운영체제</category>
      <author>warpmemory</author>
      <guid isPermaLink="true">https://warpmemory.tistory.com/166</guid>
      <comments>https://warpmemory.tistory.com/166#entry166comment</comments>
      <pubDate>Mon, 15 Jun 2020 18:20:32 +0900</pubDate>
    </item>
    <item>
      <title>웹 사이트 SSL/TLS 지원 프로토콜 확인</title>
      <link>https://warpmemory.tistory.com/165</link>
      <description>&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;2020년 상반기에 &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;4대 주요 웹브라우저 회사인 &lt;/span&gt;Google, Microsoft, Apple, Mozilla의 브라우저에서 TLS 1.0 및 1.1 지원을 종료한다고 합니다. 현재 TLS 프로토콜은 TLS 1.0, 1.1, 1.2, 1.3의 4가지 버전이 있지만, 1.0, 1.1은 POODLE 및 DEAST와 같은 공격에 취약한 것으로 알려져 있습니다. 이에 OpenSSL을 명령어로 프로토콜에 따라서 접속이 가능한지 확인 하는 방법을 소개합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;OpenSSL로 프로토콜 접속 테스트&lt;/h2&gt;
&lt;p&gt;openssl의 s_client 명령어와 프로토콜 옵션을 넣어서, 특정 프로토콜로 접속이 가능한지 확인할 수 있습니다. 정상적으로 접속이되면, 인증서 정보 및 접속 정보가 출력되고 종료 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1585117959248&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# openssl s_client -connect naver.com:443 -tls1  
CONNECTED(00000003)
depth=3 /C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
verify return:1
depth=2 /C=US/ST=New Jersey/L=Jersey City/O=The USERTRUST Network/CN=USERTrust RSA Certification Authority
verify return:1
depth=1 /C=GB/ST=Greater Manchester/L=Salford/O=Sectigo Limited/CN=Sectigo RSA Organization Validation Secure Server CA
verify return:1
depth=0 /C=KR/postalCode=13561/ST=Gyeonggi-do/L=Seongnam-si/streetAddress=6, Buljeong-ro/O=NAVER Corp./OU=Information Security Team/OU=Hosted by Korea Information Certificate Authority, Inc./OU=PremiumSSL Wildcard/CN=*.www.naver.com
verify return:1
---
Certificate chain
 0 s:/C=KR/postalCode=13561/ST=Gyeonggi-do/L=Seongnam-si/streetAddress=6, Buljeong-ro/O=NAVER Corp./OU=Information Security Team/OU=Hosted by Korea Information Certificate Authority, Inc./OU=PremiumSSL Wildcard/CN=*.www.naver.com
   i:/C=GB/ST=Greater Manchester/L=Salford/O=Sectigo Limited/CN=Sectigo RSA Organization Validation Secure Server CA
 1 s:/C=GB/ST=Greater Manchester/L=Salford/O=Sectigo Limited/CN=Sectigo RSA Organization Validation Secure Server CA
   i:/C=US/ST=New Jersey/L=Jersey City/O=The USERTRUST Network/CN=USERTrust RSA Certification Authority
 2 s:/C=US/ST=New Jersey/L=Jersey City/O=The USERTRUST Network/CN=USERTrust RSA Certification Authority
   i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
 3 s:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
   i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIHnTCCBoWgAwIBAgIRAPG4tSHPCotEtG1VzRODH4owDQYJKoZIhvcNAQELBQAw
gZUxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
BgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDE9MDsGA1UE
AxM0U2VjdGlnbyBSU0EgT3JnYW5pemF0aW9uIFZhbGlkYXRpb24gU2VjdXJlIFNl
cnZlciBDQTAeFw0xOTA0MTAwMDAwMDBaFw0yMTA0MjgyMzU5NTlaMIIBFjELMAkG
A1UEBhMCS1IxDjAMBgNVBBETBTEzNTYxMRQwEgYDVQQIEwtHeWVvbmdnaS1kbzEU
MBIGA1UEBxMLU2VvbmduYW0tc2kxFzAVBgNVBAkTDjYsIEJ1bGplb25nLXJvMRQw
EgYDVQQKEwtOQVZFUiBDb3JwLjEiMCAGA1UECxMZSW5mb3JtYXRpb24gU2VjdXJp
dHkgVGVhbTFAMD4GA1UECxM3SG9zdGVkIGJ5IEtvcmVhIEluZm9ybWF0aW9uIENl
cnRpZmljYXRlIEF1dGhvcml0eSwgSW5jLjEcMBoGA1UECxMTUHJlbWl1bVNTTCBX
aWxkY2FyZDEYMBYGA1UEAwwPKi53d3cubmF2ZXIuY29tMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEAri825vCxtjFOswvvlJ0Nm1UEY80kt33LbKmjqFnM
S9CiB7VODBp7e3Sw09F4Q2gu98L3BNEhR245O06ClFUj5mq9JJnGrRGcmjp/PhTJ
puYnPxlHdRXOsAYK/j97GJTpM05Xzzm94N/6Shr6h+LDvtZ7MDc9tNHv5ZquxBxx
tRvfnYAiZp0+zzWocCp2bj2ghvRlhXp7MRhT1S8BV1SwrN1aOjaua2hmjmBC9jav
6VOc72K5jNBhAsPQ0iFYmc1cFCCch6LFQaGXwssDfmVVRjSeRwRwIcJbiyVShaqY
gk9FtgSln3tc1Z60/89PsGgOItpIVoWwk/rgkzSAIkQvRQIDAQABo4IDYjCCA14w
HwYDVR0jBBgwFoAUF9nWJSdn+THCSUPZMDZEjGypT+swHQYDVR0OBBYEFLh6Zc2P
k8619JQ6JoHvw+9/CdsyMA4GA1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMB0G
A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBKBgNVHSAEQzBBMDUGDCsGAQQB
sjEBAgEDBDAlMCMGCCsGAQUFBwIBFhdodHRwczovL3NlY3RpZ28uY29tL0NQUzAI
BgZngQwBAgIwWgYDVR0fBFMwUTBPoE2gS4ZJaHR0cDovL2NybC5zZWN0aWdvLmNv
bS9TZWN0aWdvUlNBT3JnYW5pemF0aW9uVmFsaWRhdGlvblNlY3VyZVNlcnZlckNB
LmNybDCBigYIKwYBBQUHAQEEfjB8MFUGCCsGAQUFBzAChklodHRwOi8vY3J0LnNl
Y3RpZ28uY29tL1NlY3RpZ29SU0FPcmdhbml6YXRpb25WYWxpZGF0aW9uU2VjdXJl
U2VydmVyQ0EuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNv
bTApBgNVHREEIjAggg8qLnd3dy5uYXZlci5jb22CDXd3dy5uYXZlci5jb20wggF9
BgorBgEEAdZ5AgQCBIIBbQSCAWkBZwB1ALvZ37wfinG1k5Qjl6qSe0c4V5UKq1Lo
GpCWZDaOHtGFAAABagYQtsUAAAQDAEYwRAIgcvnYKlDj5iiMyXUXDZaL+3klOjFl
1kpDV8smCZmgrsUCIFLq43RudmteYHp/Vz13MfOjpeQ1spviyauCe/zA9XVzAHYA
RJRlLrDuzq/EQAfYqP4owNrmgr7YyzG1P9MzlrW2gagAAAFqBhC2xAAABAMARzBF
AiAGC+BNdF49ESvhqGhprDN0SndEXXp8Bvu8lCgPpJGkJgIhANuhe20ajyfGk0m5
e07meCD6NP5roWv/kdtA9yESZsITAHYAXNxDkv7mq0VEsV6a1FbmEDf71fpH3KFz
lLJe5vbHDsoAAAFqBhC27gAABAMARzBFAiB4z/lDFMMQDEIR7HuYO5m2oVFVgsyG
slTJz9S9OUVhmQIhAO2S+srpfoOTAYLYXStlidzGdOql4RUuCUOUyhJ1/eybMA0G
CSqGSIb3DQEBCwUAA4IBAQAOYLCmqVASHh1ybN8AMGpTvnVglf4G7EOZVffQ0A/b
EZzfKT1amG6Ha24P5REPZs81/nHH0biLTN5LusRU9wPWzxpnxyZKAsyuPP9zxc9K
2h0quJIEZMTNy6JDP1BU6BHnGlz7TeuLfmcm/H3EeKcU6m5LiyB+W8q5c7ND5Sv6
/nIuwZolhF2EeLjVZ+gTFjvqEaBtnXLWyNr7XIV5xpqSXyFDOeHcRfTVA7UZH3j/
JmmmIlwcdsvUAZ1nNXxFX/xQ1C5aiqe0fJuLTa8glfPzYvZwjG88Kx0KFSvcbFEF
rCcMKOi42bm/30le9Ul2rHH4wLaGoZemkjz0uxDbanpR
-----END CERTIFICATE-----
subject=/C=KR/postalCode=13561/ST=Gyeonggi-do/L=Seongnam-si/streetAddress=6, Buljeong-ro/O=NAVER Corp./OU=Information Security Team/OU=Hosted by Korea Information Certificate Authority, Inc./OU=PremiumSSL Wildcard/CN=*.www.naver.com
issuer=/C=GB/ST=Greater Manchester/L=Salford/O=Sectigo Limited/CN=Sectigo RSA Organization Validation Secure Server CA
---
No client certificate CA names sent
---
SSL handshake has read 6174 bytes and written 413 bytes
---
New, TLSv1/SSLv3, Cipher is AES128-SHA
Server public key is 2048 bit
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : AES128-SHA
    Session-ID: 6BCE041B1F64BC3876272307D8B4AA679C5319FF7592FF97A5CBE75137CAFBFA
    Session-ID-ctx: 
    Master-Key: 819D24CDBECE180F26286CEE10AF96BBB34BDF98D1A0A5F24638CB7D117DE795A39639ABB5FD37AA63EEB2CB0B0B2BF4
    Key-Arg   : None
    Krb5 Principal: None
    Start Time: 1585117802
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
---
closed&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;프로토콜 옵션은 다음과 같습니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;Option&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;Description&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;-ssl2&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;just&amp;nbsp;use&amp;nbsp;SSLv2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;-ssl3&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;just&amp;nbsp;use&amp;nbsp;SSLv3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;-tls1_2&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;just&amp;nbsp;use&amp;nbsp;TLSv1.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;-tls1_1&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;just&amp;nbsp;use&amp;nbsp;TLSv1.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;-tls1&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;just&amp;nbsp;use&amp;nbsp;TLSv1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;-dtls1&lt;span style=&quot;color: #333333;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;just&amp;nbsp;use&amp;nbsp;DTLSv1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>엔지니어링</category>
      <category>OpenSSL</category>
      <category>Protocol</category>
      <category>s_client</category>
      <category>version</category>
      <author>warpmemory</author>
      <guid isPermaLink="true">https://warpmemory.tistory.com/165</guid>
      <comments>https://warpmemory.tistory.com/165#entry165comment</comments>
      <pubDate>Wed, 25 Mar 2020 19:50:52 +0900</pubDate>
    </item>
    <item>
      <title>crontab 실행 환경 변수 설정</title>
      <link>https://warpmemory.tistory.com/164</link>
      <description>&lt;p&gt;간혹 shell에서 직접 실행하면, 정상적으로 잘 동작하는 스크립트가 &lt;span style=&quot;letter-spacing: 0px;&quot;&gt;crontab에 등록하면 정상적을 동작하지 않는 경우가 발생하곤 합니다. &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;대부분 shell의 환경 변수와 crontab의 환경 변수가 달라서 발생을 하게 됩니다. &lt;span style=&quot;color: #333333;&quot;&gt;스크립트 내에서 외부 명령어를 실행하는 경우에 PATH 환경변수가 달라서 명령어 위치를 찾지 못해서 에러가 발생하는 경우가 대표적인 예입니다. 이런 문제를 해결하기 위해서 crontab 실행 시 환경 변수를 맞춰서 실행하는 방법을 소개합니다.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;환경 변수 확인&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;현재 로그인된 shell의 환경 변수 값을&amp;nbsp; 확인 하는 방법은 set 명령어를 이용하면 확인 할 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1585100303277&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# set |egrep '^PATH'
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;/etc/crontab 수정&lt;/h2&gt;
&lt;p&gt;/etc/profile, /etc/profile.d/* 설정을 통해서 &lt;span style=&quot;color: #333333;&quot;&gt;shell 로그인시&lt;/span&gt; 환경변수를 수정할 수 있는 것처럼, /etc/crontab 파일에서 crontab 실행 환경 변수 설정을 할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1585097108438&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root

# For details see man 4 crontabs

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name  command to be executed&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위 설정은 crontab 전역 설정이라고 보면되는데, crontab은 설정 순서&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;crontab 실행 시 환경 변수 지정&lt;/h2&gt;
&lt;p&gt;crontab 설정의 실행 명령에 환경변수를 포함하여, 실행할 수 있습니다. 예를 들어 /root/backup.py 스크립트에서 /usr/local/bin/rsync 명령어를 사용하여 파일 싱크를 해야 한다면,&lt;/p&gt;
&lt;pre id=&quot;code_1585099475177&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import os

os.system(&quot;rsync -a /home /home_backup&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;crontab 실행 시에 PATH=/usr/local/bin을 앞에 넣어서 실행하게 되면, &lt;span style=&quot;color: #333333;&quot;&gt;/usr/local/bin/rsync 절대 경로가&lt;/span&gt; 아닌 rsync 로만 실행을 한경우에도 &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;/usr/local/bin/rsync가 실행되게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1585098612259&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;0 5 * * * PATH=/usr/local/bin /root/backup.py&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>엔지니어링</category>
      <category>cron</category>
      <category>crond</category>
      <category>crontab</category>
      <category>Environ</category>
      <category>환경변수</category>
      <author>warpmemory</author>
      <guid isPermaLink="true">https://warpmemory.tistory.com/164</guid>
      <comments>https://warpmemory.tistory.com/164#entry164comment</comments>
      <pubDate>Wed, 25 Mar 2020 19:40:45 +0900</pubDate>
    </item>
  </channel>
</rss>