Vim 플러그인을 설치하기 위한 기본 bash 스크립트가 있다고 가정해 보겠습니다.
#!/usr/bin/env bash
plugins=(
tpope/vim-endwise
tpope/vim-fugitive
tpope/vim-surround
tpope/vim-unimpaired
)
rm -rf $HOME/.vim/pack/bundle/*
mkdir $HOME/.vim/pack/bundle/start
installplugin() {
plugin=”$(echo “$1" | sed -e ‘s/.*[\/]//’)”
git clone –depth=1 -q https://github.com/$1.git \
$HOME/.vim/pack/bundle/start/$plugin
rm -rf $HOME/.vim/pack/bundle/start/$plugin/.git*
echo $plugin installed!
}
for repo in ${plugins[@]}; do
installplugin “$repo” &
done
wait
이는 배열의 각 저장소를 plugins
복제하고 ~/.vim/pack/bundle/start
이를 비동기식으로 수행합니다.
지금은 스크립트의 비동기 요소( &
의 끝에 위치)를 무시합니다.installplugin “$repo” &
.
Installing $plugin
시작주어진 플러그인의 설치 프로세스) 매초마다 진행률 표시줄로 Done.
해당 플러그인을 마친 후 같은 줄에 출력하고 다음 플러그인을 계속할 수 있습니까?
이 문제에 대한 나의 견해는 다음과 같습니다.
#!/usr/bin/env bash
plugins=(
tpope/vim-endwise
tpope/vim-fugitive
tpope/vim-surround
tpope/vim-unimpaired
)
rm -rf $HOME/.vim/pack/bundle/*
mkdir $HOME/.vim/pack/bundle/start
progressbar() {
until [ $installed -eq 1 ]; do
sleep 0.1
echo -n '.'
done
}
installplugin() {
installed=0
echo -n "Installing $plugin"
progressbar &
plugin=”$(echo “$1" | sed -e ‘s/.*[\/]//’)”
git clone –depth=1 -q https://github.com/$1.git \
$HOME/.vim/pack/bundle/start/$plugin
rm -rf $HOME/.vim/pack/bundle/start/$plugin/.git*
installed=1
echo ' Done.'
}
for repo in ${plugins[@]}; do
installplugin “$repo”
done
wait
작동하지 않지만 이유를 이해하지 못합니다.
해결하기가 간단하다고 생각합니다. 원본 스크립트가 비동기라는 것을 기억하면 Installing
각 메시지의 출력이 맨 아래부터 몇 줄인지 기억한 다음 설치될 때까지 점으로 줄을 업데이트해야 하기 때문에 해결하기가 더 복잡해집니다. 해당 플러그인. 앞서 설명한 진행률 표시줄의 기본 형태를 표시하려면 원본 스크립트를 수정해야 합니까?
답변1
쉘 변수는 함수 installed
내 (하위 쉘 환경에서)와 함수 내에서 두 개의 서로 다른 변수이기 때문에 작동하지 않습니다 . 백그라운드 작업으로 시작하기 때문에 함수는 하위 셸에서 실행됩니다. 함수가 시작되면 상위 환경에서 값을 상속하지만 상위는 하위 환경(subshell )에서 새 값을 설정할 수 없습니다.progressbar
installplugin
progressbar
progressbar
이는 여전히 progressbar
백그라운드 작업으로 작동하지만 무한 루프를 종료하도록 트랩을 설정할 수 있습니다. 주 함수는 foo
적절한 신호를 보내 트랩을 완료하고 트리거합니다.
progressbar () {
trap 'break' USR1
while printf '.' >&2; do
sleep 0.25
done
}
foo () {
progressbar & pid="$!"
echo 'working...'
sleep 5
echo 'done.'
kill -s USR1 "$pid"
}
foo