썬더 버드 나 파이어 폭스와 같은 킬러 애플리케이션이 시스템 패키지 관리자를 통해 업데이트되는 동안 어떻게 실행되는지 궁금합니다. 이전 코드는 업데이트되는 동안 어떻게됩니까? 프로그램이 실행되는 동안 자체적으로 업데이트되는 프로그램을 작성하려면 어떻게해야합니까?
썬더 버드 나 파이어 폭스와 같은 킬러 애플리케이션이 시스템 패키지 관리자를 통해 업데이트되는 동안 어떻게 실행되는지 궁금합니다. 이전 코드는 업데이트되는 동안 어떻게됩니까? 프로그램이 실행되는 동안 자체적으로 업데이트되는 프로그램을 작성하려면 어떻게해야합니까?
답변:
먼저 파일을 대체하는 몇 가지 전략이 있습니다.
쓰기 위해 기존 파일을 열고 0 길이로 자른 다음 새 내용을 씁니다. 덜 일반적인 변형은 기존 파일을 열고 기존 내용을 새 내용으로 덮어 쓰고 파일이 더 짧은 경우 새 길이로 자릅니다.
echo 'new content' >somefile
이전 파일을 제거 하고 동일한 이름으로 새 파일을 작성하십시오. 쉘 용어로 :
rm somefile
echo 'new content' >somefile
임시 이름으로 새 파일에 쓴 다음 새 파일을 기존 이름으로 이동 하십시오. 이동하면 이전 파일이 삭제됩니다. 쉘 용어로 :
echo 'new content' >somefile.new
mv somefile.new somefile
전략의 차이점을 모두 나열하지는 않겠습니다. 여기서 중요한 몇 가지만 언급하겠습니다. stategy 1을 사용하면 현재 프로세스를 사용하는 프로세스가있는 경우 프로세스는 업데이트중인 새 컨텐츠를 봅니다. 프로세스에서 파일 내용이 동일하게 유지 될 것으로 예상되는 경우 약간의 혼동이 발생할 수 있습니다. 이것은 파일을 열어 둔 프로세스에 관한 것입니다 ( 문서 에서 lsof
또는 문서 에서 볼 수있는 대화식 응용 프로그램은 일반적으로 파일을 편집기에서 열어서) 대화 형 응용 프로그램은 일반적으로 파일을 열어 두지 않습니다. "문서 열기"작업을 수행하고 "문서 저장"작업 중에 파일을 위의 전략 중 하나를 사용하여 바꿉니다./proc/PID/fd/
전략 2 및 3을 사용하면 일부 프로세스에서 파일을 somefile
연 경우 컨텐츠 업그레이드 중에 이전 파일이 열린 상태로 유지됩니다. 전략 2를 사용하면 실제로 파일을 제거하는 단계는 디렉토리에서 파일 항목 만 제거합니다. 그것으로 이어지는에는 디렉토리 엔트리가 없을 때 파일 자체는 제거 (일반 유닉스 파일 시스템에를,있을 수 하나 개 이상의 디렉토리와 동일한 파일에 대한 항목 ) 및 어떤 프로세스가 오픈이 없습니다. 이를 관찰하는 방법은 다음과 같습니다. 파일은 sleep
프로세스가 종료 될 때만 제거됩니다 ( rm
디렉토리 항목 만 제거).
echo 'old content' >somefile
sleep 9999999 <somefile &
df .
rm somefile
df .
cat /proc/$!/fd/0
kill $!
df .
전략 3을 사용하면 새 파일을 기존 이름으로 이동하는 단계에서 이전 컨텐츠로 이어지는 디렉토리 항목이 제거되고 새 컨텐츠로 이어지는 디렉토리 항목이 작성됩니다. 이것은 하나의 원 자성 작업으로 이루어 지므로이 전략에는 큰 이점이 있습니다. 프로세스가 언제든지 파일을 열면 이전 내용이나 새 내용을 볼 수 있습니다. 혼합 된 내용이나 파일이 혼합되지 않을 위험이 없습니다 기존.
Linux에서 실행 파일을 실행하여 전략 1을 시도하면 오류가 발생합니다.
cp /bin/sleep .
./sleep 999999 &
echo oops >|sleep
bash: sleep: Text file busy
"텍스트 파일"은 불분명 한 역사적인 이유로 실행 코드 가 들어있는 파일을 의미합니다 . 리눅스는 다른 많은 유닉스 변형과 마찬가지로 실행중인 프로그램의 코드를 덮어 쓰지 않습니다. 몇 가지 유닉스 변형은 이것을 허용하여 새 코드가 이전 코드를 잘 수정하지 않은 한 충돌을 일으 킵니다.
Linux에서는 동적으로로드 된 라이브러리의 코드를 덮어 쓸 수 있습니다. 사용중인 프로그램이 중단 될 수 있습니다. ( sleep
시작할 때 필요한 모든 라이브러리 코드를로드하기 때문에이 기능 을 관찰하지 못할 수 있습니다 . 수면 후 유용한 무언가를 수행하는보다 복잡한 프로그램을 시도하십시오 perl -e 'sleep 9; print lc $ARGV[0]'
.)
인터프리터가 스크립트를 실행중인 경우 스크립트 파일은 인터프리터에 의해 일반적인 방식으로 열리므로 스크립트 덮어 쓰기를 방지 할 수 없습니다. 일부 인터프리터는 첫 줄을 실행하기 전에 전체 스크립트를 읽고 구문 분석하고 다른 인터프리터는 필요에 따라 스크립트를 읽습니다. 실행 중에 스크립트를 편집하면 어떻게됩니까?를 참조하십시오 . 그리고 어떻게 리눅스 거래 쉘 스크립트? 상세 사항은.
전략 2와 3은 실행 파일에도 안전합니다. 실행 파일 (및 동적으로로드 된 라이브러리)은 파일 디스크립터가 있다는 의미에서 파일을 열지는 않지만 매우 유사한 방식으로 동작합니다. 일부 프로그램이 코드를 실행하는 한 파일은 디렉토리 항목이 없어도 디스크에 남아 있습니다.
대부분의 패키지 관리자는 전략 3을 사용하여 위에서 언급 한 주요 이점 때문에 파일을 교체합니다. 언제든지 파일을 열면 유효한 버전이됩니다.
응용 프로그램 업그레이드가 중단 될 수있는 위치는 하나의 파일을 업그레이드하는 것이 원 자성이지만 응용 프로그램이 여러 파일 (프로그램, 라이브러리, 데이터 등)로 구성된 경우 전체를 업그레이드하는 것이 아닙니다. 다음과 같은 일련의 이벤트를 고려하십시오.
3 단계에서, 이전 버전의 애플리케이션의 실행중인 인스턴스가 새 버전에서 데이터 파일을 여는 중입니다. 이것이 작동하는지 여부는 응용 프로그램, 파일의 파일 및 수정 된 파일의 양에 따라 다릅니다.
업그레이드 후에도 이전 프로그램이 여전히 실행 중임을 알 수 있습니다. 새 버전을 실행하려면 이전 프로그램을 종료하고 새 버전을 실행해야합니다. 패키지 관리자는 일반적으로 업그레이드시 데몬을 종료하고 다시 시작하지만 최종 사용자 응용 프로그램은 그대로 둡니다.
일부 데몬에는 데몬을 종료하지 않고 업그레이드를 처리하고 새 인스턴스가 다시 시작될 때까지 기다릴 때 서비스가 중단되는 특별한 절차가 있습니다. 이것은 init 의 경우에 필요하며 이는 죽일 수 없습니다. init 시스템은 실행중인 인스턴스 호출 execve
이 자신을 새 버전으로 교체 하도록 요청하는 방법을 제공합니다 .
unlink
나중에 다루는 것처럼 실제로는 단지 약간 혼란 스럽 습니다. "기존 이름을 대체"할 수도 있지만 여전히 다소 혼란 스럽습니다.
프로그램이 실행되는 동안 업그레이드를 실행할 수 있지만 실행중인 프로그램은 실제로 이전 버전입니다. 이전 바이너리는 프로그램을 닫을 때까지 디스크에 남아 있습니다.
설명 : Linux 시스템에서 파일은 단지 inode이므로 여러 개의 링크가있을 수 있습니다. 예 : /bin/bash
당신이 볼은 그냥 링크입니다 inode 3932163
내 시스템에. 링크를 발행하여 어떤 inode가 어떤 링크를 수행하는지 찾을 수 있습니다 ls --inode /path
. 파일 (inode)은 해당 파일을 가리키는 링크가없고 프로그램에서 사용하지 않는 경우에만 제거됩니다. 패키지 관리자 업그레이드시 /usr/bin/firefox
먼저 링크를 해제 (하드 링크 제거 /usr/bin/firefox
) 한 다음 /usr/bin/firefox
다른 inode (새 firefox
버전 을 포함하는 파일)에 대한 하드 링크 라는 새 파일을 만듭니다 . 이전 inode는 이제 사용 가능으로 표시되며 새 데이터를 저장하기 위해 재사용 할 수 있지만 디스크에 남아 있습니다 (아이 노드는 파일 시스템을 빌드 할 때만 생성되며 절대 삭제되지 않습니다). 다음에 시작할 때firefox
새로운 것이 사용됩니다.
실행하는 동안 "업그레이드"하는 프로그램을 작성하려면 내가 생각할 수있는 유일한 해결책은 자체 바이너리 파일의 타임 스탬프를 주기적으로 확인하고 프로그램의 시작 시간보다 최신 인 경우 다시로드하는 것입니다.
apt
업그레이드 작업? Iceweasel
( Firefox
)을 포함하여 문제없이 실행중인 프로그램을 업그레이드 할 수 있습니다 .
dpkg
)는 파일을 덮어 쓰지 않습니다. 대신 링크를 해제하고 동일한 이름으로 새 것을 넣습니다. 설명을 위해 링크 된 질문과 답변을 참조하십시오.
ln
(하드 링크)로 이름을 추가하면 더 많은 것을 가질 수 있습니다 . rm
(링크 해제)로 이름을 제거 할 수 있습니다 . 실제로 파일을 직접 삭제할 수는 없으며 이름 만 제거하십시오. 파일 이름이없고 추가로 열려 있지 않은 경우 커널은 해당 파일을 삭제합니다. 실행중인 프로그램에는 실행중인 파일이 열려 있으므로 모든 이름을 제거한 후에도 파일이 계속 남아 있습니다.
썬더 버드 나 파이어 폭스와 같은 킬러 응용 프로그램이 시스템 패키지 관리자를 통해 어떻게 업데이트되고 있는지 궁금합니다. 글쎄, 나는 이것이 실제로 잘 작동하지 않는다고 말할 수있다 ... 패키지 업데이트가 실행되는 동안 열어두면 Firefox가 나에게 끔찍한 영향을 미쳤다. 때로는 너무 세게 죽이고 다시 시작해야했습니다. 너무 깨져서 제대로 닫을 수도 없었습니다.
이전 코드는 업데이트되는 동안 어떻게됩니까? 일반적으로 Linux에서는 프로그램이 메모리에로드되므로 프로그램이 실행되는 동안 디스크의 실행 파일이 필요하지 않거나 사용되지 않습니다. 실제로 실행 파일을 삭제할 수도 있고 프로그램은 신경 쓰지 않아야합니다 ... 그러나 일부 프로그램에는 실행 파일이 필요할 수 있으며 특정 OS (예 : Windows)는 실행 파일을 잠그므로 삭제 또는 이름 변경 / 이동을 방지 할 수 있습니다. 프로그램이 실행 중입니다. Firefox는 실제로 상당히 복잡하고 GUI (사용자 인터페이스)를 구축하는 방법을 알려주는 많은 데이터 파일을 사용하기 때문에 중단됩니다. 패키지 업데이트 중에 이러한 파일을 덮어 쓰거나 (업데이트 됨) 메모리에있는 이전 Firefox 실행 파일이 새 GUI 파일을 사용하려고하면 이상한 일이 발생할 수 있습니다.
프로그램이 실행되는 동안 자체적으로 업데이트되는 프로그램을 작성하려면 어떻게해야합니까? 귀하의 질문에 이미 많은 답변이 있습니다. 이 체크 아웃 : /programming/232347/how-should-i-implement-an-auto-updater을 그건 그렇고, 프로그래밍에 대한 질문은 더 나은에 StackOverflow에 꺼져 있습니다.