Alert
์ด ๊ธ์ Claude Code์ ๋์์ ๋ฐ์ ์์ฑ๋์์ต๋๋ค
TL;DR
- shell script ๋์์ฑ ๋ฌธ์ ๋ cron ์ค๋ณต ์คํยท๊ณต์ ํ์ผ ๋์ ์์ ์์ ๋ฐ์
flock์ ํ์ผ์ ์ ๊ธ์ ๊ฑธ์ด ํ ๋ฒ์ ํ๋๋ง ์๊ณ ๊ตฌ์ญ์ ์ง์ ์ํค๋ ๋๊ตฌ- flock์ advisory lock โ ๋ชจ๋๊ฐ ํธ์ถํด์ผ ์๋ฏธ๊ฐ ์๊ณ ๊ฐ์ ์ฐจ๋จ์ ์๋
- ์ ๊ธ ์์ ์๋ ํ๋ก์ธ์ค๊ฐ ์๋๋ผ open file description(OFD), ์ถฉ๋ ํ์ ์ inode ๋จ์
- ํ๋ก์ธ์ค ์ข ๋ฃ ์ FD๊ฐ ๋ซํ๋ฉฐ ์ ๊ธ ์๋ ํด์ โ stale lock ์ํ์ด ๋ฎ์
- ์ด์์ฑ ํ๊ฒฝ์์
mkdirยทset -o noclobberยทln์ ์์์ฑ์ผ๋ก ๋์ฒด
1. ์ ํ์ํ๊ฐ โ shell script์ ๋์์ฑ ๋ฌธ์
์ฌ๋ฌ ํ๋ก์ธ์ค๊ฐ ๊ฐ์ ์์์ ๋์์ ๊ฑด๋๋ฆฌ๋ฉด ์์ธก ๋ชป ํ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค. shell script์์ ๊ฐ์ฅ ํํ ๋ ์ํฉ์ ์ด๋ ๋ค.
- cron ์ค๋ณต ์คํ: 5๋ถ๋ง๋ค ๋๋ ์์ ์ด ํ ๋ฒ์ 5๋ถ์ ๋๊ธฐ๋ฉด, ์ด์ ์คํ์ด ์ ๋๋ฌ๋๋ฐ ์ ์คํ์ด ๋ ๋ฌ๋ค. ๋ฐฑ์ ์ด ๊ฒน์ณ ๋๊ฑฐ๋ ๊ฐ์ ํ์ผ์ ๋์์ ์จ์ ๊นจ์ง๋ค.
- ๊ณต์ ํ์ผ ๋์ ์์ : ๋ ์คํฌ๋ฆฝํธ๊ฐ ๊ฐ์ ํ์ผ์ ๋ง๋ถ์ด๊ฑฐ๋ ์นด์ดํฐ๋ฅผ ์ฌ๋ฆฌ๋ฉด, ์ฝ๊ณ ์ฐ๋ ์ฌ์ด์ ๋ผ์ด๋ค์ด ๊ฐฑ์ ์ด ์ ์ค๋๋ค.
์นด์ดํฐ ์ฆ๊ฐ๋ง ๋ด๋ ์์์ ์ด์ง ์๋ค.
# ๋ ํ๋ก์ธ์ค๊ฐ ๋์์ ๋๋ฉด ๊ฐฑ์ ์ด ์ ์ค๋ ์ ์๋ค
count=$(cat counter.txt) # ๋ ๋ค "10"์ ์ฝ๊ณ
echo $((count + 1)) > counter.txt # ๋ ๋ค "11"์ ์ด๋ค โ 12๊ฐ ์๋๋ผ 11์ด๋ ๊ฒ โ๋์์ ๋ค์ด์ค๋ฉด ์ ๋๋ ๊ตฌ๊ฐโ์ ์๊ณ ๊ตฌ์ญ(critical section)์ด๋ผ ๋ถ๋ฅธ๋ค. ํ ๋ฒ์ ํ๋์ ํ๋ก์ธ์ค๋ง ๋ค์ด๊ฐ๊ฒ ๋ง๋๋ ๊ฒ์ด ๋์์ฑ ์ฒ๋ฆฌ์ ํต์ฌ์ด๋ค. ์์ ์ ๋ณ๋ ฌ๋ก ๋๋ฆฌ๋ ์ชฝ์ Job Control์์ ๋ค๋ค๊ณ , ์ด ๊ธ์ ๋ฐ๋๋ก ๊ฒน์น์ง ์๊ฒ ๋ง๋ ์ชฝ์ ๋ค๋ฃฌ๋ค.
2. ์ ๊ธ์ ๊ธฐ๋ณธ ์์ด๋์ด
์๊ณ ๊ตฌ์ญ์ ํ ๋ฒ์ ํ๋๋ง ํต๊ณผ์ํค๋ ค๋ฉด ์ ๊ธ(lock)์ ์ด๋ค. ๋ค์ด๊ฐ๊ธฐ ์ ์ ์ ๊ธ์ ์ก๊ณ , ๋์ฌ ๋ ํผ๋ค. ์ด๋ฏธ ๋๊ฐ ์ก๊ณ ์์ผ๋ฉด ๊ธฐ๋ค๋ฆฌ๊ฑฐ๋ ํฌ๊ธฐํ๋ค.
shell์๋ ์ธ์ด ์ฐจ์์ ๋ฎคํ
์ค๊ฐ ์์ผ๋, ํ์ผ์์คํ
์ ์์์ ์ฐ์ฐ์ ์ ๊ธ์ผ๋ก ๋น๋ ค ์ด๋ค. ๋ํ๊ฐ flock์ด๊ณ , ๊ทธ ๋ฐ์ mkdirยทnoclobberยทln์ ์์์ฑ์ ์ด์ฉํ๋ ๋ฐฉ๋ฒ์ด ์๋ค(7๋ฒ).
3. flock โ ์ฐ๋ ๋ฒ
flock์ ํ์ผ์ ์ ๊ธ์ ๊ฑธ์ด ํ ๋ฒ์ ํ ํ๋ก์ธ์ค๋ง ์๊ณ ๊ตฌ์ญ์ ๋ค์ด๊ฐ๊ฒ ํ๋ค. ์ ๊ธ์ ์ ๊ธ์ฉ FD๋ก ๊ทธ ํ์ผ์ ๊ฑธ๋ฆฌ๊ณ , ํ๋ก์ธ์ค๊ฐ ๋๋ FD๊ฐ ๋ซํ๋ฉด ์๋์ผ๋ก ํ๋ฆฐ๋ค.
FD๋ฅผ ์ง์ ์ฌ๋ ํํ
exec {lock_fd}>/var/lock/myjob.lock # ์ ๊ธ์ฉ FD ์ด๊ธฐ
if ! flock -n "$lock_fd"; then
echo "์ด๋ฏธ ์คํ ์ค" >&2
exit 1
fi
# --- ์ฌ๊ธฐ๋ถํฐ ํ ๋ฒ์ ํ๋๋ง ---
long_running_job
# ์คํฌ๋ฆฝํธ๊ฐ ๋๋๋ฉด FD๊ฐ ๋ซํ๋ฉฐ ์ ๊ธ ํด์ ์ ๊ธ ํ์ผ ์ด๋ฆ์
.lockํ์ฅ์๋ ์์ ํ ๊ดํ์ด๋ค.flock์ ํ์ฅ์๋ฅผ ๋ณด์ง ์๊ณ ์๋ฌด ํ์ผ์๋(์ฌ์ง์ด ๋๋ ํฐ๋ฆฌ์๋) ๊ฑธ ์ ์๋ค. ์ ๊ธ์ ์๋ฏธ๋ ์ด๋ฆ์ด ์๋๋ผ flock๊ณผ inode์์ ๋์จ๋ค.
์๋ธ์ ธ ๋ธ๋ก ํํ
(
flock -n 9 || { echo "์ด๋ฏธ ์คํ ์ค"; exit 1; }
long_running_job
) 9>/var/lock/myjob.lock๋ช ๋ น์ ๊ฐ์ธ๋ ํํ โ cron์ ์ข๋ค
flock์ ์ ๊ธ์ ์ก์ ์ฑ ๋ช
๋ น ํ๋๋ฅผ ์คํํด ์ฃผ๊ธฐ๋ ํ๋ค. crontab์ ๊ทธ๋๋ก ๋ฃ๊ธฐ ์ข๋ค.
# job.sh๊ฐ ์ด๋ฏธ ๋๊ณ ์์ผ๋ฉด ์ด๋ฒ ์คํ์ ๊ฑด๋๋ด๋ค
flock -n /var/lock/myjob.lock /path/to/job.sh
# crontab ์์ โ 5๋ถ๋ง๋ค, ๊ฒน์น๋ฉด skip
# */5 * * * * /usr/bin/flock -n /var/lock/myjob.lock /path/to/job.sh์์ฃผ ์ฐ๋ ์ต์ :
| ์ต์ | ์๋ฏธ |
|---|---|
-n | ์ ๊ฒจ ์์ผ๋ฉด ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ์ฆ์ ์คํจ (๋ ผ๋ธ๋กํน) |
-w N | ์ต๋ N์ด ๊ธฐ๋ค๋ฆฐ ๋ค ์คํจ |
-x | ๋ฐฐํ ์ ๊ธ (์ฐ๊ธฐ, ๊ธฐ๋ณธ๊ฐ) |
-s | ๊ณต์ ์ ๊ธ (์ฝ๊ธฐ, ์ฌ๋ฟ์ด ๋์์ ๊ฐ๋ฅ) |
-u | ์ ๊ธ ํด์ (๋ณดํต FD๊ฐ ๋ซํ๋ฉฐ ์๋ ํด์ ๋ผ ์๋ต) |
exec์ ๋์ FD({fd}>) ๋ฌธ๋ฒ ์์ฒด๋ ์ด ๊ธ์์ ๋ค๋ค๋ค.
FDํ vs ๋ํผํ โ ์ธ์ ๋ญ ์ฐ๋
์ ์ธ ํํ๋ ์ ๊ธ์ ๋๊ฐ ๋ค๊ณ ์ด๋๊น์ง ๋ณดํธํ๋๋๊ฐ ๋ค๋ฅด๋ค.
- ๋ํผํ
flock -n lock command:flock์ด ์ง์ ํ์ผ์ ์ด๊ณ ์ ๊ทผ ๋คcommand๋ฅผ ์์์ผ๋ก ์คํํ๊ณ , ๋๋๋ฉด ํผ๋ค. โ๋ช ๋ น ํ๋๋ฅผ ํต์งธ๋ก ์ ๊ธ ์๋โ โ cron์ ๊ฐ์ฅ ์ ๋ง๊ณ ๊ฐ๋จํ๋ค.- FDํ
exec {fd}>lock; flock -n "$fd": ์ง๊ธ ๋๋ ์ ธ ํ๋ก์ธ์ค ์์ ์ด ์ ๊ธ์ ๋ ๋ค. ์ธ๋ถ ๋ช ๋ น์ ๊ฐ์ธ๋ ๊ฒ ์๋๋ผ ์คํฌ๋ฆฝํธ ์ค๊ฐ์ ํ ๊ตฌ๊ฐ์ ์ ๊ทธ๊ณ ๊ฐ์ ํ๋ก์ธ์ค์์ ์ ธ ๋ก์ง์ ์ด์ด๊ฐ ๋ ์ด๋ค. ์์์ ์ ๋์ฐ๊ณ , ํ ๋ฒ ์ฐ ์ ๊ธ์ ์ฌ๋ฌ ๋จ๊ณ์ ๊ฑธ์ณ ๋ค๊ณ ์์ ์ ์๋ค.
4. advisory lock โ ๊ถ๊ณ ์ผ ๋ฟ, ๊ฐ์ ๊ฐ ์๋๋ค
flock์์ ๊ฐ์ฅ ์์ฃผ ์คํดํ๋ ์ง์ ์ด๋ค. flock์ด ๊ฑฐ๋ ์ ๊ธ์ advisory lock(๊ถ๊ณ ์ ์ ๊ธ)์ด๋ค. ์ปค๋์ด โ์ด ํ์ผ์ ์ ๊ฒผ์ผ๋ ์๋ฌด๋ ๋ชป ๊ฑด๋๋ฆฐ๋คโ๊ณ ๊ฐ์ ํ๋ ๊ฒ ์๋๋ผ, flock์ ํธ์ถํ ์ชฝ๋ผ๋ฆฌ๋ง ์๋ก ์๋ณดํ๋ ์ฝ์์ด๋ค.
# A: ์ ๋๋ก ์ ๊ทธ๊ณ ๋ค์ด๊ฐ ํ๋ก์ธ์ค
exec {fd}>/var/lock/data.lock
flock "$fd"
echo "์์ ์ค" >> data.txt
# B: flock์ ์ ๋ถ๋ฅด๊ณ ๊ทธ๋ฅ ์ฐ๋ ํ๋ก์ธ์ค
echo "๋ผ์ด๋ค๊ธฐ" >> data.txt # ๋งํ์ง ์๋๋ค. ๊ทธ๋ฅ ์จ์ง๋ค.์ฆ ์ ๊ธ์ ๋ชจ๋๊ฐ ๊ฐ์ ์ ๊ธ ํ์ผ์ flock์ ํธ์ถํ ๋๋ง ํจ๋ ฅ์ด ์๋ค. ํ ๋ช ์ด๋ผ๋ ํ์กฐํ์ง ์์ผ๋ฉด ๊ทธ๋๋ก ๋ซ๋ฆฐ๋ค. ๊ทธ๋์ โ์ด ์์์ ์ด ์ ๊ธ์ผ๋ก ๋ณดํธํ๋คโ๋ ๊ท์น์ ์ฝ๋ ์ ์ฒด๊ฐ ์ง์ผ์ผ ํ๋ค.
advisory vs mandatory
- advisory(๊ถ๊ณ ): ์ฐธ์ฌ์๊ฐ ์๋ฐ์ ์ผ๋ก ์ ๊ธ์ ํ์ธํ๋ค. flock๊ณผ POSIX
fcntl์ ๊ธ์ด ์ฌ๊ธฐ ์ํ๊ณ , ์ ๋์ค ์ ๊ธ์ ์ฌ์ค์ ์ ๋ถ ๊ถ๊ณ ์ ์ด๋ค.- mandatory(๊ฐ์ ): ์ปค๋์ด
read/write์์ฒด๋ฅผ ๋ง๋๋ค. Linux์๋ ์์์ง๋ง ๊ตฌํ์ด ๋ถ์์ ํ๊ณ ์ํํด ์ฌ์ค์ ํ๊ธฐ๋๋ค(์ปค๋ 5.15๋ถํฐ ์ ๊ฑฐ ๊ฐ๋ฅ, ๊ธฐ๋ณธ ๋น๊ถ์ฅ). ํ์ค์ ์ผ๋ก ์ ธ ์คํฌ๋ฆฝํธ์ ์ ๊ธ์ ์ ๋ถ advisory๋ผ๊ณ ๋ณด๋ฉด ๋๋ค.
advisory๋ผ๋ ์ฌ์ค์ ์ค๋ฌด์ ํจ์๋ ๋์ด๋ค.
- ์ ๊ธ ํ์ผ๊ณผ ์ค์ ๋ณดํธ ๋์์ ๋ค๋ฅธ ํ์ผ์ด์ด๋ ๋๋ค. ํํ ์์
ํ์ผ์ด ์๋๋ผ ๋ณ๋์
.lockํ์ผ์ flock์ ๊ฑด๋ค. ์ ๊ธ์ ์ฝ์์ผ ๋ฟ์ด๋ผ ์ด๋์ ๊ฑธ๋ ์ฐธ์ฌ์๋ง ๊ฐ์ผ๋ฉด ๋๋ค. - ์ ๊ธ ํ์ผ์ ๋ด์ฉ์ด ๋น์ด ์์ด๋ ๋๋ค. flock์ ๋ฐ์ดํฐ๊ฐ ์๋๋ผ โ์ด๋ฆฐ ํ์ผโ ์ํ์ ๊ฑฐ๋ ๊ฒ์ด๋ผ ๋น ํ์ผ๋ก ์ถฉ๋ถํ๋ค.
5. ์ปค๋์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ๋ โ OFD์ inode
flock์ ๋์์ ์ ํํ ์ดํดํ๋ ค๋ฉด lock์ owner๊ฐ ๋ฌด์์ธ์ง ์์์ผ ํ๋ค. ๋ต์ ํ๋ก์ธ์ค๋ FD ๋ฒํธ๋ ์๋ open file description(OFD)์ด๋ค.
open ํ์๋งํผ OFD๊ฐ ์๊ธด๋ค
P1: exec {fd1}>/tmp/lock open() โโ
P2: exec {fd2}>/tmp/lock open() โโผโโบ OFD_1 / OFD_2 / OFD_3 โโโบ inode (the lock file)
P3: exec {fd3}>/tmp/lock open() โโ three separate OFDs shared by all three
open()์ ํธ์ถํ ๋๋ง๋ค ์ปค๋์ OFD(struct file)๋ฅผ ์๋ก ๋ง๋ ๋ค. ์ธ ํ๋ก์ธ์ค๊ฐ ๊ฐ์ ๊ฒฝ๋ก๋ฅผ ์ด์ด๋ OFD๋ 3๊ฐ๊ฐ ์๊ธฐ๊ณ , ์
๋ค ๊ฐ์ inode๋ฅผ ๊ฐ๋ฆฌํจ๋ค. ์ด ์์ ์ lock์ด ํ๋๋ ์๋ค. open๊ณผ lock์ ๋ณ๊ฐ์ ์ฐ์ฐ์ด๋ค.
inode์ struct file์ ์ ์ฒด
file descriptor๋ ์ฌ์ค 3๋จ์ผ๋ก ์ฐ๊ฒฐ๋๋ค. ์ด ๊ทธ๋ฆผ์ ์ก์ผ๋ฉด ์ ๋์์ด ๋๋ ทํด์ง๋ค.
fd (per process) โโโบ open file description (struct file) โโโบ inode (struct inode)
fd 3 โโ
fd 4 โโดโโบ struct file โ one per open() call
f_pos : file offset
f_flags : status flags (O_APPEND, O_NONBLOCK, ...)
f_count : reference count (raised by fork / dup)
f_inode : โโโบ struct inode โ one per file
i_ino : inode number
i_mode : type & permissions
i_size : size
i_flctx : lock list (flock records live here)
- inode: the file ์์ฒด์ metadata. typeยทpermissionยทsizeยทtimestampยทlink countยทdata block ์์น์ ๋ํด lock list(
i_flctx)๋ฅผ ํ๋๋ค. ํ file๋น ํ๋์ด๊ณ , ๊ฐ์ ๊ฒฝ๋ก๋ฅผ ์ฌ๋ฌ ๋ฒ ์ด์ด๋ inode๋ ํ๋๋ค. - struct file (open file description):
open()ํ ๋ฒ์ ํํํ๋ค. file offsetยทaccess modeยทstatus flagsยทinode pointerยทreference count๋ฅผ ๊ฐ์ง๋ค.fork/dup์ ์๋ก ๋ง๋ค์ง ์๊ณ reference count๋ง ์ฌ๋ฆฐ๋ค.
flock์ lock record๋ ์ด ์ค inode์ ๋งค๋ฌ๋ฆฐ lock list(i_flctx)์ ๋ค์ด๊ฐ๊ณ , ๊ฐ record๊ฐ ์๊ธฐ owner OFD๋ฅผ ๊ฐ๋ฆฌํจ๋ค. ๊ทธ๋์ lock์ disk์ ์ ์ฅ๋์ง ์๋, ๊ทธ file(inode)์ ๋ถ์ runtime metadata๋ค. โ๋๊ฐ ์ ๊ฐ๋โ๋ record ์์ OFD๋ก ์๋ณ๋๋ค. lock์ด inode๋ณ๋ก ๋
๋ฆฝ์ด๋ผ, ํ file์ lock์ ๋ค๋ฅธ file์ ์ ํ ์ํฅ์ ์ฃผ์ง ์๋๋ค.
flock์ inode์ lock list์ OFD๋ฅผ owner๋ก ์ ๋๋ค
P1์ด flock -n "$fd1"(exclusive)์ ํธ์ถํ๋ฉด ์ปค๋์ ์ด๋ ๊ฒ ์ฒ๋ฆฌํ๋ค.
fd1โ P1์ OFD_1๋ก ํด์- ๊ทธ OFD๊ฐ ๊ฐ๋ฆฌํค๋ inode์ flock lock list๋ฅผ ํ์ธ
- ์ถฉ๋ํ๋ lock์ด ์์ผ๋ฉด owner๊ฐ OFD_1์ธ lock record๋ฅผ inode์ ์ถ๊ฐํ๊ณ
0๋ฐํ
์ด์ P2๊ฐ flock -n "$fd2"๋ฅผ ํธ์ถํ๋ฉด:
fd2โ P2์ OFD_2๋ก ํด์- inode์ lock list์์ OFD_1์ด ์์ ํ exclusive lock์ ๋ฐ๊ฒฌ
- ๊ทธ ์ ๊ธ์ ์์ OFD๊ฐ ๋ด OFD์ ๋ค๋ฅด๋ฏ๋ก ์ถฉ๋ โ
-n์ด๋ผ ์ฆ์ ์คํจ(flock์ด 0์ด ์๋ ์ฝ๋๋ก ์ข ๋ฃ) โ โ์ด๋ฏธ ์คํ ์คโ
-n์ด ์์ผ๋ฉด P2๋ wait queue์์ ์ ๋ค๊ณ , P1์ด ํ๋ฉด ๊นจ์ด๋ ๋ค์ ์๋ํ๋ค.
์ โOFD๊ฐ ๋ค๋ฅด๋ฉด ์ถฉ๋โ์ธ๊ฐ
flock์ ์ถฉ๋ ๊ท์น์ ํ ์ค์ด๋ค. ๊ฐ์ inode์, ๋ค๋ฅธ OFD๊ฐ ์์ ํ, ํธํ๋์ง ์๋ lock์ด ์์ผ๋ฉด ์ถฉ๋์ด๋ค.
| held \ requested | shared (s) | exclusive (x) |
|---|---|---|
| shared (s) | OK | conflict |
| exclusive (x) | conflict | conflict |
์๋ฅผ ๋ค์ด P1์ด shared(-s)๋ก ์ก๊ณ ์์ด๋ P2๊ฐ exclusive(-x)๋ฅผ ์์ฒญํ๋ฉด ์ถฉ๋ํด ๋งํ๋ค. exclusive๋ ๋
์ ์ ์๊ตฌํ๊ธฐ ๋๋ฌธ์ด๋ค. ๋ฐ๋๋ก ๋ ๋ค shared๋ฉด ์ฌ๋ฌ reader๊ฐ ๋์์ ๋ค์ด๊ฐ๋ค.
- ์ธ ํ๋ก์ธ์ค๊ฐ ๊ฐ์ open โ OFD๊ฐ ์ ์ผ๋ก ๊ฐ๋ฆผ โ ์๋ก ๋จ์ด๋ผ ๊ฒฝํฉํ๋ค. ์ด๊ฒ ์๋ํ mutual exclusion์ด๋ค.
- ํ ํ๋ก์ธ์ค๊ฐ ์ด๊ณ
fork/dupํ๋ฉด ์์์ ๊ฐ์ OFD๋ฅผ ๋ฌผ๋ ค๋ฐ๋๋ค. ์ด๋ flock์ ๊ฐ์ owner๋ก ๋ณด๊ณ ์ถฉ๋์ํค์ง ์๋๋ค. ๋์ ํ๋์ lock์ ๊ณต์ ํ๋ค.
lock ํด์ ์์
- ๋ช
์์
flock -u, ๋๋ - OFD๊ฐ ์๋ฉธํ ๋ โ ๊ทธ OFD๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ง์ง๋ง fd๊ฐ ๋ซํ ๋. ํ๋ก์ธ์ค๊ฐ ์ ์ ์ข
๋ฃํ๋
kill -9๋ก ์ฃฝ๋ ์ปค๋์ด fd๋ฅผ ์ ๋ถ ๋ซ์ OFD๊ฐ ์ ๋ฆฌ๋๋ฉฐ lock๋ ์ฌ๋ผ์ง๋ค. flock์ด crash์ ๊ฐํ ์ด์ ๋ค. lock file์ ๋จ์๋ lock ์์ฒด๋ ํ๋ฆฐ๋ค. - ๋จ,
dup์ผ๋ก ๋ณต์ ํ fd๊ฐ ๋จ์ ์์ผ๋ฉด OFD reference count๊ฐ 0์ด ์๋๋ผ lock์ ์ ์ง๋๋ค.
6. flock์ ํจ์
- inode ๊ธฐ์ค์ด๋ผ ์ ๊ธ ํ์ผ์ ์ง์ฐ๋ฉด ์ ๋๋ค. ๋๊ฐ
rmํ๊ณ ๋ค๋ฅธ ํ๋ก์ธ์ค๊ฐ ์๋ก ๋ง๋ค๋ฉด inode๊ฐ ๋ฐ๋์ด, ์ inode๋ฅผ ์ก์ ์ ๊ธ๊ณผ ์ inode๋ฅผ ์ฐ ํ๋ก์ธ์ค๊ฐ ์๋ก ๋ชป ๋ง๋๋ค. ์ ๊ธ ํ์ผ์ ๊ณ ์ ํด ๋๊ณ ์ง์ฐ์ง ์๋๋ค. >๋ ๋งค๋ฒ ์๋ผ๋ธ๋ค. ์ ๊ธ์ ๋ฌดํดํ์ง๋ง, ์ ๊ธ ํ์ผ์ PID ๊ฐ์ ๋ด์ฉ์ ๋จ๊ธฐ๋ ค๋ฉด>(O_TRUNC) ๋์<>๋ก ์ด์ด ์๋ฅด์ง ์๋๋ค. ๋ฆฌ๋ค์ด๋ ์ ์ฐ์ฐ์๋ณ open ํ๋๊ทธ๋ Bash Shell Script 2์ ์ ๋ฆฌ๋ผ ์๋ค.- ๋คํธ์ํฌ ํ์ผ์์คํ ์ฃผ์. ์ค๋๋ NFS์์๋ flock์ด ๋ก์ปฌ์์๋ง ๋์ํ๊ฑฐ๋ ์ ๋๋ก ์ ๊ฑธ๋ฆด ์ ์๋ค. ๋ถ์ฐ ํ๊ฒฝ์ ์ ๊ธ์ ์ ์ฉ ๋๊ตฌ(RedisยทetcdยทConsul ๋ฑ)๊ฐ ์์ ํ๋ค.
- ์๋ธ์
ธ ๋ธ๋ก์ ๋ณ์๋ ๋ฐ์ผ๋ก ์ ๋์จ๋ค.
( flock ...; ... ) 9>lock์์์ ๋ฐ๊พผ ๋ณ์๋ ์๋ธ์ ธ์ด ๋๋๋ฉด ์ฌ๋ผ์ง๋ค. ๊ฒฐ๊ณผ๋ ํ์ผ์ด๋ stdout์ผ๋ก ๋นผ๋ธ๋ค.
7. flock ์์ด โ ์ด์์ฑ ์๋ ๋์
flock์ Linux์ util-linux ๋๊ตฌ๋ผ macOS์ ๊ธฐ๋ณธ ํ์ฌ๋์ง ์๋๋ค. ์์ชฝ์์ ๋๋ ์ ๊ธ์ด ํ์ํ๋ฉด ํ์ผ์์คํ
์์ฒด์ ์์์ ์ฐ์ฐ์ ์ด๋ค. ํต์ฌ์ โ์ด๋ฏธ ์์ผ๋ฉด ์คํจํ๋, ์์ฑ๊ณผ ๊ฒ์ฌ๊ฐ ํ ๋ฒ์ ์ผ์ด๋๋โ ์ฐ์ฐ์ด๋ค.
mkdir โ ๋๋ ํฐ๋ฆฌ ์์ฑ์ ์์์ฑ
lockdir=/tmp/myjob.lock.d
if mkdir "$lockdir" 2>/dev/null; then
trap 'rmdir "$lockdir"' EXIT
long_running_job
else
echo "์ด๋ฏธ ์คํ ์ค"; exit 1
fimkdir์ ์ด๋ฏธ ์์ผ๋ฉด ์คํจํ๋ค. ์์ฑ๊ณผ ์กด์ฌ ๊ฒ์ฌ๊ฐ ํ ์ฐ์ฐ์ด๋ผ ๊ฒฝ์์ด ๋ผ์ด๋ค ํ์ด ์๋ค.
set -o noclobber โ >์ O_EXCL
lockfile=/tmp/myjob.lock
if ( set -o noclobber; echo "$$" > "$lockfile" ) 2>/dev/null; then
trap 'rm -f "$lockfile"' EXIT
long_running_job
else
echo "์ด๋ฏธ ์คํ ์ค"; exit 1
finoclobber๋ฅผ ์ผ๋ฉด >๊ฐ ๊ธฐ์กด ํ์ผ์ ๋ฎ์ด์ฐ์ง ์๊ณ ์คํจํ๋ค. ๋ด๋ถ์ ์ผ๋ก O_CREAT|O_EXCL์ด๋ผ ์์์ ์ด๋ค. ๋ค์ผ๋ก PID๋ฅผ ์ ์ด ๋๋ฉด ๋๊ฐ ์ก์๋์ง ์ ์ ์๋ค.
ln์ผ๋ก ํ๋๋งํฌ๋ฅผ ๊ฑฐ๋ ๋ฐฉ๋ฒ(ln ์์ํ์ผ ์ ๊ธํ์ผ)๋ ์์์ ์ด๋ผ, ์ค๋๋ NFS์์๊น์ง ๋์์ด ํ์ํ ๋ ์ด๋ค.
๊ณตํต ํ๊ณ โ stale lock
flock๊ณผ ๋ฌ๋ฆฌ ์ด ๋ฐฉ๋ฒ๋ค์ ์ ๊ธ์ด ํ์ผ์ด๋ ๋๋ ํฐ๋ฆฌ์ ์กด์ฌ ์์ฒด๋ค. ํ๋ก์ธ์ค๊ฐ kill -9๋ก ์ฃฝ์ผ๋ฉด trap์ด ๋ชป ๋์ ์ ๊ธ์ด ๋จ๋๋ค. ๋ค์ ์คํ์ด ์์ ๋งํ ์ ์๋ค. ๋ณด์์ฑ
์ ๋ ๊ฐ์ง๋ค. ์ ๊ธ์ PID๋ฅผ ์ ๊ณ ๊ทธ PID๊ฐ ์ด์ ์๋์ง(kill -0 "$pid") ํ์ธํด ์ฃฝ์์ผ๋ฉด ํ์ํ๊ฑฐ๋, ์ ๊ธ ํ์ผ์ด ๋๋ฌด ์ค๋๋๋ฉด ํ์ํ๋ค.
| ๋ฐฉ๋ฒ | ์ด์์ฑ | ํฌ๋์ ์ ์๋ ํด์ | ๋น๊ณ |
|---|---|---|---|
flock | Linux ์ค์ฌ | O | FD๊ฐ ๋ซํ๋ฉฐ ํ๋ฆผ. ๊ฐ์ฅ ๊ฒฌ๊ณ ํ์ง๋ง macOS ์์ |
mkdir | ๋์ | X | ์ด๋์๋ ๋์, stale ์ํ |
noclobber > | ๋์ | X | PID ๊ธฐ๋ก์ด ์ฌ์, stale ์ํ |
ln ํ๋๋งํฌ | ๋์ | X | ์ค๋๋ NFS์์๋ ์์์ , stale ์ํ |
8. ์ค์ ํจํด ๋ชจ์
cron ์ค๋ณต ๋ฐฉ์ง (ํ ์ค)
# ์ด์ ์คํ์ด ์ ๋๋ฌ์ผ๋ฉด ์ด๋ฒ์ ์กฐ์ฉํ ๊ฑด๋๋ด๋ค
# */5 * * * * /usr/bin/flock -n /var/lock/sync.lock /home/me/sync.shcron ์คํฌ๋ฆฝํธ์ ๊ฑฐ์ ๊ณต์์ฒ๋ผ ์ฐ์ธ๋ค.
๊ธฐ๋ค๋ ธ๋ค ์คํ (ํ์์์)
# ์ต๋ 30์ด ๊ธฐ๋ค๋ ธ๋ค๊ฐ ๋ชป ์ก์ผ๋ฉด ํฌ๊ธฐ
flock -w 30 /var/lock/job.lock /path/to/job.sh์ ๊ธ ํ์ผ ์์น
- ์ฌ๋ถํ
๋ ๋น์๋ ๋๋ ์งง์ ์ ๊ธ:
/run(๋๋/var/run),/tmp - ์์คํ
์๋น์ค:
/var/lock - ์ฌ์ฉ์ ๋จ์:
$XDG_RUNTIME_DIR
๊ด์ฐฐ โ ์ง๊ธ ๊ฑธ๋ฆฐ ์ ๊ธ ๋ณด๊ธฐ
Linux์์ ํ์ฌ ๊ฑธ๋ฆฐ ์ ๊ธ์ ์ง์ ํ์ธํ๋ค.
cat /proc/locks # FLOCK ADVISORY WRITE ... ํํ๋ก ์ถ๋ ฅ
lslocks # ์ฌ๋์ด ์ฝ๊ธฐ ์ข์ ํADVISORY๋ผ๊ณ ์ฐํ๋ ๋ฐ์ flock์ด ๊ถ๊ณ ์ ์ ๊ธ์์ด ํ ๋ฒ ๋ ํ์ธ๋๋ค.
/proc/locks๋ flock๋ง ๋ณด์ฌ์ฃผ๋ ๊ฒ ์๋๋ค์ปค๋์ด ๋ค๊ณ ์๋ ๋ชจ๋ ํ์ผ ์ ๊ธ์ด ๋์ค๊ณ , ํ์ ์นธ์ผ๋ก ์ข ๋ฅ๊ฐ ๊ฐ๋ฆฐ๋ค.
FLOCKโflock()(BSD ์ ๊ธ)POSIXโfcntl(F_SETLK)ยทlockfOFDLCKโ open file description lock (์ต์ POSIX)ํ ํ์ ๋๋ต์ ํ์์
1: FLOCK ADVISORY WRITE 12345 08:01:1234567 0 EOF๊ผด์ด๋ค. ์์๋๋ก ๋ฒํธ, ํ์ , ๊ถ๊ณ /๊ฐ์ , ๋ชจ๋(WRITE=exclusiveยทREAD=shared), PID,major:minor:inode, ์์ยท๋ offset์ด๋ค. flock ํ์ ํญ์ADVISORY์ด๊ณ inode ์นธ์ผ๋ก ์ด๋ ํ์ผ์ธ์ง ์๋ณ๋๋ค.