'2017/03'에 해당되는 글 3건

  1. 2017.03.08 [Ubuntu/Linux] zip 버그...
  2. 2017.03.08 Bash print call stack at ERR(trap)
  3. 2017.03.08 SW refactoring시 가장 주의해야 할 점.

[Ubuntu/Linux] zip 버그...

Domain/Linux 2017.03.08 22:08

Ubuntu(14.04 - 64bit)에서 test해 보면 zip의 경우

- zip archive의 크기가 4G근처

- 몇몇 entry를 삭제

- file을 zip에 추가해서 4G가 이상


=> 이렇게 될때, zip entry가 깨어지는 현상을 볼 수 있다.

명백하게 zip bug로 보이는데..


같은 시나리오에서 7z을 사용할 경우 문제가 없음을 확인할 수 있다.

또한 7z의 경우, 내부적으로 병렬로 pkzip을 수행하는 것으로 보인다.

$ time 7z ...

의 command로 확인해보면, 바로 알 수 있다. 또한 속도도 빠르다!

신고
Trackback 0 : Comment 0

Bash print call stack at ERR(trap)

Language/Bash 2017.03.08 22:03


At head of script file:

(CODE-1)
trap 'on_error "${FUNCNAME[@]} ${BASH_LINENO[@]} $LINENO"' ERR
trap 'on_exit' EXIT

Someone may wonder why don't write code like below because it is easier to handle arguments.

(CODE-2)
trap 'on_error "$LINENO ${FUNCNAME[@]} ${BASH_LINENO[@]}"' ERR
trap 'on_exit' EXIT

I don't know there is any documented information related with this. But, results of my experiments are saying that (CODE-2) doens't work as expected.
In case of (CODE-2), my test shows that only latest function-stack information is passed to 'on_error' trap function.
I don't have any idea about the reason. More investigation is required for this.
But anyway, (CODE-1) works well.
So, you can use those arguments to print function call stack at bash.
You may need to use 'BASH_SOURCE' array too, if your bash uses other files, too.



And there is one interesting case. See follow code.

<< Test environment >>
bash: GNU bash, version 4.3.46(1)-release (x86_64-pc-linux-gnu)
OS: Linux XXXX 4.4.0-64-generic #85-Ubuntu SMP Mon Feb 20 11:50:30 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

-------------------------- TEST-1 -----------------------------
<< a.sh >>
function on_err() {
    echo "error"
}

function on_exit() {
    echo "exit"
}

trap on_err ERR
trap on_exit EXIT

myval=$(echo u | grep p)  # global variable


$ bash -eE a.sh
error
exit

-------------------------- TEST-2 -----------------------------

<< a.sh >>
function on_err() {
    echo "error"
}

function on_exit() {
    echo "exit"
}

trap on_err ERR
trap on_exit EXIT

function f0() {
    local myval=$(echo u | grep p)  # local variable in function
}

f0

$ bash -eE a.sh
exit

---------------------------------------------------------------

Even if errtrace is enabled(-E option), 'error' is NOT printed at TEST-2.
Then, is this means 'ERR' is NOT trapped at TEST-2? That is, does 'on_err' not executed?
Let's have a look following code.

-------------------------- TEST-3 -----------------------------

<< a.sh >>
function on_err() {
    echo "error"
}

function on_exit() {
    echo "exit"
}

trap on_err ERR
trap on_exit EXIT

function f0() {
    myval=$(echo u | grep p)  # NOT local variable anymore.
}

f0

$ bash -eE a.sh
error
exit

-------------------------- TEST-4 -----------------------------

<< a.sh >>
function on_err() {
    echo "error" 1>&2  # echo to standard error.
}

function on_exit() {
    echo "exit"
}

trap on_err ERR
trap on_exit EXIT

function f0() {
    local myval=$(echo u | grep p)  # local variable
}

f0

$ bash -eE a.sh
error
exit

-------------------------- TEST-5 -----------------------------


function on_err() {
    echo "error" 1>&2  # echo to stderr
}

function on_exit() {
    echo "exit"
}

trap on_err ERR
trap on_exit EXIT

myval=$(echo u | grep p)  # assign to global variable.


$ bash -eE a.sh
error
error
exit


-------------------------- TEST-6 -----------------------------


function on_err() {
    true  # There is no echo
}

function on_exit() {
    echo "exit"
}

trap on_err ERR
trap on_exit EXIT

myval=$(echo u | grep p)  # asign to global variable


$ bash -eE a.sh
exit

---------------------------------------------------------------

It's very interesting, isn't it?
Further investigation will be continued for this issue.



신고

'Language > Bash' 카테고리의 다른 글

Bash print call stack at ERR(trap)  (0) 2017.03.08
Trackback 0 : Comment 0

SW refactoring시 가장 주의해야 할 점.

Essay/Software 2017.03.08 21:58

Code refactoring의 어려운 점은 이미 잘 알려진 바와 같다.
하지만, 그 문제의 복잡성 측면에서 보면, 작은 규모의 refactoring - file 혹은 class 단위 변경 - 은, 대규모 - 특히 코드의 구조 혹은 설계를 바꾸는 정도 - refactoring 에 비할 바가 못된다.

legacy 코드의 구조가 한계에 부딫혀, 재설계->재구현 을 고민할 정도의 상황을 가정해 보자.
이때, 가장 많이 고민하는 것은 아마도 "SW 재작성" vs "대규모 refactoring"일 것이다.
그리고, 어떠한 이유에서든, "refactoring"을 하기로 결정한 상황이라면 어떨까?
(실제, SW를 처음부터 새로 작성하는 것에 대한 Risk는 많이 언급되어 지고 있다.)

필자의 경험에 따르면, 이때 가장 중요한 것은
- refactoring의 단위를 적당히 작은 단계(step)로 분류하고,
- 각 step에서는 그 목적에 해당하는 refactoring만 수행
하는 것이다.

정말로 간단하고, 쉬워보이지 않는가?
하지만, 이게 정말 쉽지 않다.

Refactoring을 주제로 하는 많은 이야기들은, '좋은 구조', 'refactoring 시점' 등등 기술적인 측면을 다루고 있다.
그런데, 막상 필자가 실제로 heavy하게 사용되고 있는 SW를 refactoring하는 경험을 해보니, 정작 문제는 앞서 언급했던 두 가지에 있었다.

보통, 대규모 refactoring은 아래의 단계를 거쳐서 진행될 것이다.
- 현재 SW의 문제점 논의
- Refactoring의 범위 결정
- 새로운 SW구조에 대한 설계 철학 공유
- SW의 최종 형태 공유.
- 각 주제별로 refactring 시작.

하지만, 이런식의 진행은 'legacy SW의 상태'와 '최종 SW의 상태' 사이에 큰 차이가 있기 때문에, 그 끝이 좋지 못한 경우가 많다.
많은 양의 변화를 한꺼번에 진행하면, refactoring과정에서 발생한 오류를 찾아내기 너무 힘들어서, 결국 refactoring 코드를 버리거나, 아니면 SW 재작성에 버금가는(혹은 그 이상의) 노력이 들어가게 된다.
이론적으로는 이런 내용들을 대부분의 개발자들이 잘 알고 있지만, 실제로는 어떨까?

예를 들어, class간의 관계를 재 설정하는 refactoring진행 중, code의 context와 맞지 않는 변수 이름을 발견했다면? 혹은 code style이 잘못된 곳을 발견했다면?
대부분의 경우, 아주 작은 수정이므로, 겸사겸사 같이 수정하면서 진행할 것이다.
이것은, 마치 "거실 바닥 정리"라는 과정 중 "벽에 작은 얼룩을 발견"한 경우, 그냥 지나치지 못하고, 잠깐 시간내어서 얼룩을 지우는 것과 같다.
혹은, SW의 "Feature creep"과도 일맥상통해 보인다.
이런 식의 작은 side-refactoring들이 모여서, 한 step의 복잡성을 증가시키고, 결국 해당 step을 포기하고 처음부터 다시 진행하도록 만든다.

따라서, refactroing을 계획할 때는 앞서 언급한 것처럼, 그 단계를 잘게 나누어야 한다.
물론, 각 단계별로, "새로운 구조" + "legacy 구조" 의 형태를 지켜 내기 위한 overhead가 필요하므로, 너무 잘게 분리할 경우, 이 overhead 비용이 너무 커질 수 있으므로 주의해야 한다.


신고
Trackback 0 : Comment 0

티스토리 툴바