defaults system 사용법

login item에 항목을 추가하는 인스톨러를 만들기 위해 참 많은 시간을 허비했다.
PakcageMaker의 안정적이지 않은 동작으로 애를 먹었었고, 사실 최근 버젼들은 비교적 안정적이었다. 하지만 역시 이해하기 힘든 부분이 있었고, 또한 무슨 일이 왜 발생하는지 인스톨 로그를 보고선 파악하기 힘든 면이 있었다. 이에 대해서 별도로 포스팅을 하겠는데, 그전에 defaults system에 대해서 언급을 해야겠다.
Windows에는 registry란 것이 있다. 여기에 어떤 프로그램을 인스톨했으며, 그 프로그램에서 어떤 세팅을 어떻게 했으며 등등을 기록해 놓는 것이다. 이 registry는 Windows를 쓰면 쓸수록 성능이 떨어지게 만드는 주범 중의 하나이기도 하다. 이런 이유에는 registry를 사용하는 Windows 자체의 문제이기도 하지만, InstallShield나 MSI installer setup project를 만드는게 참 어렵기 때문에, 인스톨 프로그램을 만드는 사람들이 제대로 모든 도큐먼트를 충분히 이해하고 만들지 못하는 이유가 있기도 하다.

Mac은 비교적 깔끔하게 이런 관리를 한다. registry란 단일의 공간이 있다기 보다는 preference를 /Library/Preference나 ~/Library/Preference에 각 프로그램 별로 저장을 한다. com.apple.Safari.plist와 같은 것이 바로 그것이다. 산업계 표준에 맞추어서 그 이름도 com.apple.Safari처럼 해 놓았고, plist는 XML이라 그 내용을 보기도 편하다. 단 text XML이라 그 파일이 커지면 느려지고 커지는 단점도 있어서 요새는 Binary XML도 이용하는 추세이다.
Windows에서처럼 registry란 단일 공간내에 기록될 필요가 없어서, 저장공간 (메모리건 하드디스크건)을 차지하는데 그 공간이 비대해질 염려도 적다. 그러므로 세팅을 찾는데 시간도 적게 걸린다. ( Windows Sys Internals 툴을 이용해보면 Windows가 수시로 registry를 업데이트하는데 시간을 많이 보내고 있음을 볼 수있다. Mac에선 적어도 이런 일은 최소화가 된다. 왜 Windows가 아무일도 안하고 가만히 있는 거 같은데도 수시로 HDD를 긁어대는지 그 이유는 이런데 있다. 물론 background process들도 계속 돌고 있고, 그들이 registry에 써대는 이유도 있지만, 기본적으로 Windows는 registry관리에 CPU time의 일정 부분을 줄기차게 할애한다. )

Mac에서는 각 프로그램들에서 세팅을 하면 그것이 이런 XML파일에 저장이 된다. 프로그램이 설치되서 실행이 되면, 그리고 뭔가 세팅을 저장하면 비로소 이 XML이 생기는데, 아쉽게도 프로그램을 지웠을때, 이 파일들이 자동으로 없어지진 않는다. 이렇게 남아도 Windows처럼 registry란 중앙 집중적인 공간에 저장되지 않기 때문에 퍼포먼스 하락에 그다지 일조하지 않는다. 하지만 Mac에는 다른 문제점이 있는데, 여기에 버그가 좀 있다. 바로 receipt DB란 것이다. 여기에 대해선 뒤에서 언급하기로 하고…

아무튼 세팅을 저장하기 위해선 해당 프로그램을 열어서 거기서 지원하는 preference… 메뉴를 이용해서 주로 바꾸게 되는데…
해당 프로그램을 열지 않고서 바꾸려면 어떻게 해야 하는가? 바로 그 XML 파일들을 직접 열어서 바꿔주면 된다. 근데 이 부분은 user interaction이 들어가서, 때때로 shell script등에서 해주기엔 곤란한 부분이 있다. 이때 바로 쓰는게 defaults system이란 것이다. 종종 Mac OS X Hints와 같은 웹사이트에서 이것을 이용해서 hidden setting을 이용하는게 보인다. 특히 Shell programming을 많이 하게 될 Sys Admin들 입장에서는 defaults system을 아는게 상당히 중요하다.
그러다보면 많이 보게 되는게 바로 MAN page인데.. 문제는 이 MAN page의 설명이 당췌 알아보기가 힘들게 되어 있다는 것이다. MAN page가 그렇듯이 항상 긴 설명에 예제는 거의 없다. 어떤 것을 정의 해 놓고서 그게 뭘 뜻하는 건지 설명이 없기 일쑤다.

자 한번 보자

write domain key 'value'
  Writes value as the value for key in domain.
  value must be a property list, and must be enclosed
  in single quotes.
  For example:
     defaults write com.companyname.appname "Default Color" '(255, 0, 0)'
  sets the value for Default Color to an array containing the strings 255, 0, 0
  (the red, green, and blue components).
  Note that the key is enclosed in quotation marks because it contains a space.

write domain 'plist'
  Overwrites the defaults information in domain with that given as plist.
plist must be a property list representation of a dictionary,
and must be enclosed in single quotes.
  For example:
    defaults write com.companyname.appname '{ "Default Color" = (255, 0, 0); "Default Font" = Helvetica; }';
  erases any previous defaults for com.companyname.appname and writes the values for the two names into the defaults system.

자 이 설명으로 key value 쌍으로 세팅할때는 어떻게 하는지, plist는 어떻게 생겼는지 알 수가 있다.

자 그럼 다음을 보자.

-array      Allows the user to specify an array as the value for the
                given preference key:

                  defaults write somedomain preferenceKey -array element1 element2 element3

                 The specified array overwrites the value of the key if the
                 key was present at the time of the write. If the key was not
                 present, it is created with the new value.

-array-add  Allows the user to add new elements to the end of an array
                 for a key which has an array as its value. Usage is the same
                 as -array above. If the key was not present, it is created
                 with the specified array as its value.

-dict       Allows the user to add a dictionary to the defaults database
               for a domain.  Keys and values are specified in order:

                  defaults write somedomain preferenceKey -dict key1 value1 key2 value2

               The specified dictionary overwrites the value of the key if
               the key was present at the time of the write. If the key was
               not present, it is created with the new value.

-dict-add   Allows the user to add new key/value pairs to a dictionary
               for a key which has a dictionary as its value. Usage is the
               same as -dict above. If the key was not present, it is cre-
               ated with the specified dictionary as its value.

저 array element가 어떻게 생겼는지 알 수가 없다. 또한 dictionary 경우엔 key과 value로 어떤 형태의 데이터를 받아들이는지 알기가 힘들다.
도대체 element는 어떤 type의 것일까?

Login item을 넣기 위해서 구글에서 찾아보았다.
근데 그다지 도움이 되지를 않았다. 대개 간단한 경우에 대해서만 했기 때문이다.
그래서 고생 고생끝에 되는 형태를 찾았는데..

#!/bin/sh
defaults write loginwindow AutoLaunchedApplicationDictionary -array-add '{"Hide" = "True"; "Path" = "/Applications/NEXIO Sync.app";}'
echo "Writing to defaults system is done"

자.. 위의 것은 shell script 파일로 만든 것이다. 편하게 사용하려면 execution 권한을 저 파일에 주면 되는 것이고, 일일히 sh를 호출하기 싫어서 She-Bang라인을 넣어 주었다.
음.. AutoLaunchedApplicationDictionary 아이템에 -array-add 이후의 아이템을 넣는 것인데, 그 자체가 dictionary 형태이다.
즉 한 dictionay를 array로 넣는 것이다. 왜 그럼 -dict-add를 넣으면 안될까? 그건 AutoLaunchedApplcationDictionary의 형태 때문이다. 자 보자..

loginwindow-plist

자.. AuoLaunchedApplicaitonDictionary 키 자체가 여러 아이템을 가지고 있게 되는 형태고, 그 아이템마다 세팅이 있는 것이다.
그러므로 각 아이템이 dictionary이니까, dictionary 자체를 array의 한 아이템으로 넣는 것이다.
그러므로 만약 -dict-add를 이용하면 이미 있는 item1과 item 2가 없어지면서, 한 이이템들이 아닌 AutoLaunchedApplicaitonDictionary 자체의 property들로 key와 value가 세팅이 된다.

이렇게 알고 보면 참 간단한데, 전혀 설명이 없는 상태에서 MAN 페이지의 설명만 봐서는 알기가 힘들다. add 버젼과 아닌 버젼의 차이는, add가 있는 경우는 이미 기존에 있는 것들에 덧붙여서 넣는 것이고, 없는 것은 기존에 있던 것을 갈아치우는 것이다. 이것에 대한 설명은 다행이 있다.

암튼 이렇다.

ADDED : 아.. sed에 익숙한 분이시면 sed를 이용하시는 것도 한 방법이 되겠다.
근데 text processing이 귀찮으니까, 그냥 defautls system을 이용하시는게..
sed를 이용해서 plist파일을 바꾸는 것이 여기에 포스팅 되어 있으니 참고하시면 jump start를 하는데 도움이 될 듯..

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: