bash 스크립트 (.sh) 파일이 실행되는 동안 수정할 수 있습니까?


28

script script.sh가 있는데 실행하는 데 시간이 걸립니다. 나는 그것을 실행한다 ./script.sh. 터미널 창에서 실행되는 동안 파일을 수정합니다 script.sh. 이미 실행중인 프로세스에 영향을 줍니까?

파일을 수정 한 후 수정 된 파일을 실행하므로 두 개의 실행중인 프로세스가 있습니다. 괜찮습니까?


답변:


36

스크립트를 변경할 때 디스크 (하드 디스크-영구 저장소)를 변경합니다. 스크립트를 실행하면 스크립트가 메모리 (RAM)에로드됩니다.

따라서 스크립트에 대한 변경 사항은 실행중인 스크립트에 영향을 미치지 않으며 변경하기 전에 실행 한 버전을 실행합니다.

그러나 이전에 실행중인 인스턴스를 종료하지 않고 변경된 스크립트를 다시 실행하면 두 개의 스크립트 인스턴스 (변경된 인스턴스와 이전 인스턴스)가 있습니다.

스크립트가 사용하고 수정하는 리소스가 충돌 할 수 있습니다. 예를 들어, 스크립트를 사용하여 파일을 수정하는 경우 나중에 실행되는 스크립트는 해당 파일을 쓰기 위해 열 수없고 올바르게 실행되지 않습니다.

업데이트 : Unix.stackexchange.com에 대한 더 나은 답변을 알려 주신 Registered User에게 감사드립니다.

스크립트의 크기와 해당 컴파일러 / 통역사에 따라 스크립트가 부분적으로 / 완전히로드됩니다. 따라서 스크립트가 완전히로드되지 않은 경우 스크립트의 일부가 메모리에로드되면 스크립트의 변경 사항이 실행중인 인스턴스에 반영됩니다.

따라서 예상치 못한 출력을 위해 현재 실행중인 디스크에서 스크립트를 변경하지 않는 것이 좋습니다. 먼저 실행중인 인스턴스를 중지 한 다음 스크립트를 수정 한 다음 스크립트를 다시 실행하십시오.


11
완벽한 답변은 아닙니다. unix.stackexchange.com/q/121013/55673
등록 된 사용자

@registereduser : 예, 그 질문은 저의 OS 수업을 상기시켜주었습니다. 데스크탑에 손을 대 자마자 내 대답을 편집 할 것입니다 (지금 전화로)
jobin

짧은 스크립트의 경우 아무런 문제가 없을 것 같습니다.
becko

1
bash v3.2.48 ( here 참조 )로 이것을 시도했을 때 , 줄 끝을 넘어 버퍼링하지 않았습니다 (그리고 스크립트를 실행할 때 잘못 실패했습니다). 방금 bash v4.3.0으로 다시 테스트했으며 전체 (짧은) 스크립트를 버퍼링했습니다. 그래서 ... 나는 특별한 행동을하지 않을 것입니다.
Gordon Davisson

1
@RegisteredUser 모든 버전의 bash가있는 것은 아닙니다. 링크 된 예를 참조하십시오.
Gordon Davisson

4

나는 다른 답변에서 언급되지 않은 것으로 생각되는 것을 추가 할 것입니다. 파일을 편집하는 방법 에 따라 다릅니다 . 이렇게 echo "stuff" >file쉘 (다른 인스턴스)에서하면 실제로 파일을 덮어 쓰게됩니다, 나는 생각한다. 그러나 예를 들어 파일을 편집 emacs한 다음 저장하면 이런 일이 발생하지 않습니다. 대신 여기에서 편집기는 이전 파일의 이름을 일부 백업 이름 (실제로 이전 백업을 제거 할 수도 있음)으로 바꾼 다음 수정 된 버퍼 컨텐츠를 (현재 libreated) old name 으로 파일로 작성합니다 . 스크립트를 읽는 쉘 (또는 다른 인터프리터)은 거의 확실하게 파일을 한 번만 열므로, 파일 이름 의 위치와 무관합니다.파일을 열 때 파일 이름과 연결된 실제 디스크 파일 (아이 노드 번호로 식별)을 계속 읽습니다. 따라서 스크립트를 블록 단위로 읽는 경우에도 (버퍼링 된 텍스트 I / O를 사용하는 경우 가장 쉬운 솔루션 임) 파일의 이전 인스턴스에서 행을 계속 읽게되므로 편집해도 변경되지 않을 수 있습니다.


+1 Sublime Text를 편집자로 사용하고 있습니다. 파일 이름이 너무 바뀌 었는지 알고 emacs있습니까?
becko

1
필자는 대부분의 편집자가 이름을 바꾸는 계획을 사용한다고 생각하지만 (백업 버전을 유지하지 않아도) 쓰기 프로세스 중에 충돌이 발생하더라도 텍스트의 완전한 버전이 전혀 남아 있지 않을 위험을 피할 수 있습니다. "ls -i"(아이 노드 번호 표시)로 편집기의 동작을 확인할 수 있습니다.
Marc van Leeuwen

1

위의 답변은 이제 부분적으로 만 정확합니다.

현재 버전의 bash를 사용하는 경우 스크립트가 실행되는 동안 디스크에서 스크립트를 수정하면 bash가 "시도"하여 변경 사항을 메모리에로드하고 실행중인 스크립트에서이를 수행합니다. 변경 사항이 현재 실행중인 줄 다음에 오는 경우 새 줄이로드되어 실행됩니다. 그러나 이것은 bash의 추측이며 정확하거나 잘못 될 수 있습니다.

이를 수행하는 더 좋은 방법은 다음과 같은 일련의 동작입니다. 1) 스크립트를 메모리에로드 2) 디스크에서 스크립트 삭제 3) 디스크 버전을 먼저 삭제하여 디스크에 새 스크립트를 작성하면 메모리 버전과의 링크가 끊어집니다. 따라서 3 단계에서 새 버전을 제공 할 때 bash가 새 버전을 메모리 버전으로로드하려고 시도하지 않습니다.


0

@jobin의 대답은 일반적으로 정확하지만 원하는대로 할 수있는 다른 대답을 추가하겠습니다.

스크립트를 변경하고 안전한지 알고 싶다면 기존 파일이 아닌 새 파일에 쓰려고합니다. 새 파일은 이전 파일이 있던 위치에있을 수 있습니다. 새 버전을 새 파일에 쓴 다음 이전 버전 mv의 맨 위로 이동하십시오. 대체 된 파일이 여전히 존재하며 디렉토리에서 링크되지 않았습니다. 실행중인 스크립트는 계속해서 사용할 수 있으며, 해당 스크립트가 파일 핸들을 닫으면 시스템은 파일을 안전하게 정리할 수 있음을 알게됩니다 (즉시 또는 나중에).

스크립트의 동작을 즉시 작동 시키려면보다 어려운 문제가 있습니다. 스크립트 코드로 빌드해야한다고 생각합니다. Bash 스크립트는 신호를 처리 할 수 ​​있으며 (예 :와 같은 것을 잡을 수 있음 kill -USR1 [pid]) 스크립트는 일부 코드를 다시로드하여 응답 할 수 있습니다. 어쩌면 원하는 기능에 가까운 기능을 얻을 수 있지만, 당신이 무엇을하는지 알지 못하더라도, 나는 이것을 할 좋은 이유가 보이지 않습니다. 그것을 할 프로그래밍 언어.

이것을 염두에두고 작성되지 않은 스크립트의 동작을 해킹하려면 운이 좋지 않습니다. 나는 프로그래밍 작업을 불가능하게 부르는 것을 망설이고 있지만, 당신이 이런 종류의 작업에 대한 자원과 기술을 가지고 있다면 아마도 여기에 묻지 않을 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.