toBala KM King


Requires Javascript.
Linux 系統基礎- 學習筆記本 - V1.1 (2010/04/02)
<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml'/>
<!--}}}-->
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

.tabSelected{color:[[ColorPalette::PrimaryDark]];
	background:[[ColorPalette::TertiaryPale]];
	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity:60)';}
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0em 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0em 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0em 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 .3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0em 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0em 0em 0em; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0em;}
.wizardFooter .status {padding:0em 0.4em 0em 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em 0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0em; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em 0.2em 0.2em 0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em 0.2em 0.2em 0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em 1em 1em 1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0em;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0em 0em 0.5em;}
.tab {margin:0em 0em 0em 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0em 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0em 1em;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0em 0.25em; padding:0em 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0em; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px 1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0em; right:0em;}
#backstageButton a {padding:0.1em 0.4em 0.1em 0.4em; margin:0.1em 0.1em 0.1em 0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; margin:0em 3em 0em 3em; padding:1em 1em 1em 1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em 0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none ! important;}
#displayArea {margin: 1em 1em 0em 1em;}
/* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
noscript {display:none;}
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler > fields syncing permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<!--}}}-->
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These InterfaceOptions for customising TiddlyWiki are saved in your browser

Your username for signing your edits. Write it as a WikiWord (eg JoeBloggs)

<<option txtUserName>>
<<option chkSaveBackups>> SaveBackups
<<option chkAutoSave>> AutoSave
<<option chkRegExpSearch>> RegExpSearch
<<option chkCaseSensitiveSearch>> CaseSensitiveSearch
<<option chkAnimate>> EnableAnimations

----
Also see AdvancedOptions
<<importTiddlers>>
Revision 3497
''參考文章''
1. Basics of Linux system administration: Working at the console (必讀)
http://www.ibm.com/developerworks/training/kp/l-kp-command/index.html
2. 15 Examples To Master Linux Command Line History
http://www.thegeekstuff.com/2008/08/15-examples-to-master-linux-command-line-history/

{{item1{命令格式}}}
{{{
1. Unix98 : 必須要有前置破折號 (-)
2. BSD : 選項可以合併不得有前置破折號
3. GNU : 必須有二個破折號 (--)
}}}

''範例 : ''
{{{
# tar  xvfz  wget.tar.gz

# ls   -l                (後面只有字母)

# ls   --help           (後面只有單字)

# ls   -l  --all


# ls  –alh
}}}

''[註]'' 可同時執行多行命令, 例如 :  "# ls;ps"

{{item1{自定命令 (alias)}}}
{{{
# alias      (查詢自定命令)
alias ping='ping -c 4'

# alias bye=“sudo shutdown –h now”       (建立自定命令)

# unalias  bye     (刪除自定命令)
}}}

''問題 : '' 如何重新開機後, 還保留 alias 自定命令 ? (~/.bashrc)

{{item1{history 命令}}}
''Display timestamp using HISTTIMEFORMAT''

Typically when you type history from command line, it displays the command# and the command. For auditing purpose, it may be beneficial to display the timepstamp along with the command as shown below.
{{{
# export HISTTIMEFORMAT='%F %T '
# history | more
1  2008-08-05 19:02:39 service network restart
2  2008-08-05 19:02:39 exit
3  2008-08-05 19:02:39 id
4  2008-08-05 19:02:39 cat /etc/redhat-release
}}}

''Execute a specific command from history''
In the following example, If you want to repeat the command #4, you can do !4 as shown below.
{{{
# history | more
1  service network restart
2  exit
3  id
4  cat /etc/redhat-release

# !4
cat /etc/redhat-release
Fedora release 9 (Sulphur)
}}}

{{item1{命令歷程環境變數}}}
執行過的命令會存在 ~/.bash_history 這個檔中, 而 .bash_history 的大小, 由 HISTSIZE 這環境變數來決定
{{{
$ echo $HISTSIZE
1000
}}}

{{item1{Linux Bash 環境下,輸入指令不留痕跡的作法}}}
本文網址 : http://portable.easylife.tw/1717

其實在系統上留下「輸入指令的記錄」是個安全的作法,至少下了什麼指令會有一個依據,萬一下錯指令還可以看看到底做錯了什麼,只是被老闆砍頭也要有個完整的紀錄,總不能說"好像"下錯指令,或許有些錯誤不是該自己造成的啊!因此在系統下 command 的記錄還是完整的保留一下好了!

但是或許有時候會想來一個例外狀況,可能一些指令會有帶帳號密碼的,這時候當然就不會希望在系統上留下記錄,最簡單的做法就是 ''HISTSIZE=0'',不過這樣的作法所有的歷史記錄都會被清除,會不會被老闆質疑「你為什麼要把 command 記錄都刪除?」,當要查閱記錄的時候頭就大了。因此為了能繼續的有完整的指令記錄,但是又要避免掉一些敏感指令被記錄,這實就可以利用''HISTCONTROL'' 來達成這個目的。

{{op1{HISTCONTROL有簡單的三種用法:}}}

''HISTCONTROL=ignorespace''
{{{
執行以上的變數設定,之後只要是 comannd 前有空白的話,history 將不會記錄你下的 command。

$ echo wawa
wawa

$  echo bebo   #echo前有加空格
bebo


$ history | tail -2
16  echo wawa
echo bebo 那行並不會出現在history的記錄當中
17  history | tail -10
}}}

''HISTCONTROL=ignoredups''
{{{
執行以上的變數設定,之後只要是重複下的指令,只會被記錄一次。

$ echo easylife   #echo 4次easylife
easylife

$ echo easylife
easylife

$ echo easylife
easylife

$ echo easylife
easylife

$ echo good   #echo 1次good
good

$ history | tail -5
   38  echo easylife
echo easylife 4次卻只出現一筆記錄
   39  echo good
   40  history | tail -5
}}}

''HISTCONTROL=ignoreboth''
{{{
這個就是結合以上兩種,就不再示範囉!
}}}

或許有人想說這的確是不錯的一個資訊,只是到底用到的時機到底是什麼時候?我在這邊可以簡易分享我所想到的用途,首先我絕對會把HISTCONTROL=ignorespace 加到 .bashrc 裡面去,這樣以後只要登入系統就自動生效了,避免自己再去手動執行一次留下記錄 (HISTCONTROL=ooxx 的記錄),到時候老闆查歷史記錄還會問說你下那行幹嘛?有種你可以回答「做壞事」
<<toBalaNotes "history">>

///%history
//%/
&nbsp;
__{{item1{學習筆記本簡介}}}__
這是一個由單網頁 (HTML, CSS, JavaScript) 所建構的資訊工作平台 (Platform), 在這平台中你可以輕鬆的處理各式各樣資訊, 例如 網頁(XHTML), 可縮放向量圖形 (SVG), 數學標籤語言 (MathML), 同步多媒體集成語言 (SMIL), PDF 等, 並以 [標籤分類] 方式, 有效的將平台中的資訊, 轉換成個人知識庫.

學習筆記本 有提供 Wiki 語法, 可使妳快速產生網頁資訊, 更可以作為 Ajax 及 Java 程設人員的開發平台 (首創), 至於多媒體的展示能力更不在話下, 因這平台本體就是網頁, 當然可輕易展示圖片, 影片, 音樂 (JPG, GIF, AVI, WAV,..). 相信由這平台的實作, 你可以感覺單網頁平台所創造的資訊力 (force) 是無限的, 在下一個版本 (2.0) 已計劃整合 ''SQLite'', 這可使得 ''學習筆記本'' 大大提升其執行效率及文章儲存容量

__''@@font-size:14px;系統需求@@''__
|硬體|CPU : P4+, 記憶體 : 512 MB+|
|瀏覽器|Firefox 2.0+, IE 6.0+, Safari 3.1+|
|作業系統|Windows 2000/XP/Vista, Mac OS X|

__''@@font-size:14px;核心技術@@''__
學習筆記本核心技術是來自於 [[TiddlyWiki|http://www.tiddlywiki.com/]], 並與 TiddlyWiki 採用相同授權方式 (BSD OpenSourceLicense)

__{{item1{下載學習筆記本}}}__
點選 [[這裡|http://tbala.net/download/toBalaKMKNotepad.zip]] 下載大約 9 MB 的壓縮檔 (toBalaKMKNotepad.zip)

__{{item1{安裝與啟動學習筆記本}}}__
你只需將下載的壓縮檔 (toBalaKMKNotepad.zip) 解壓縮至資料磁碟機 (建議 USB 隨身碟), 這時你會看到ㄧ個名為 toBalaKMKNotepad 的資料夾,
在資料夾中快點二下 toBalaKMKNotepad.html, 系統會使用預設瀏覽器將之開啟 (目前只支援 IE 5.5+, Firefox 1.5+, Safari 3.1+)

''[注意]'' 切勿將壓縮檔 toBalaKMKNotepad.zip 解壓縮至 ''[桌面]'' 或 ''[名稱中有空白字元的目錄]'', 這樣操作會造成 ''學習筆記本'' 無法正常工作. 在 toBalaKMKNotepad 資料夾中, 存在的某些 .exe 檔 (tbsys.exe, tbjava.exe, tbjavac.exe), 會被防毒軟體誤判為病毒並隔離, 請自行設定防毒軟體, 將這些檔案視為安全檔案.

__{{item1{學習筆記本的目錄結構}}}__
{{{
toBalaKMKNotepad
       |--- img                   儲存圖檔 (png, jpg,...)
       |
       |--- movie                儲存影音檔 (avi, mov,...)
       |
       |--- music               儲存音樂檔 (mp3, mp4, wav...)
       |
       |--- documents         儲存各式文件檔 (pdf, text, doc,...)
       |
       |--- tools                 儲存隨身應用軟體 (zoomIt, Inkscape, hfs,...)
       |
       |--- ajax                  儲存 Ajax 程設人員的工具及程式 (HTML, CSS, JavaScript)
       |
       |--- java                   儲存 Java 程設人員所需的工具及程式 (J2SE, Tomcat,..)
       |
       |--- xml                   儲存各式 XML 標準資訊檔 (SVG, XHTML, MathML, ODF,...)
       |
       |--- db                     儲存 SQLite 所建立的資料庫
       |
       |--- jslib                   儲存 Ajax Framework
}}}

__{{item1{學習筆記本 - 版本記錄}}}__

''@@color:red;[V1.1 - 2008/09/30]@@''
1. 將 ImportTiddlersPlugin 更新為 4.3.3
2. toBalaJava 巨集升級為 toBalaJava2 巨集
3. toBalaAjax 巨集加入 [網頁文字編輯] 功能
4. toBalaFlashPlayer 巨集升級為 toBalaSWF2 巨集 (使用 SWFObject 2.1)
5. 新增 [更新土芭樂巨集程式碼] 按鈕
6. 新增 [匯出文章] 功能按鈕 (ExportTiddlersPlugin) 
7. 新增 toBalaBackup 巨集, 備份指定文章
8. 新增 toBalaCoreBackup 巨集, 備份 "土芭樂巨集" 程式
9. 修改 toBalaLIB 程式庫 (getMainTree, TagDigg, getTiddlerDIV)
10. 將 [版面管理員] 改版為 [控制台]

__{{item1{筆記本設定 (設定將存於瀏覽器 Cookies 中)}}}__

請簽名 <<option txtUserName>>
<<option chkGenerateAnRssFeed>> 儲存變更時,也儲存 RSS feed

__{{item1{版面設定 (設定將存於筆記本中)}}}__
<<toBalaManager>>

__{{item1{筆記本備份 (設定將存於瀏覽器 Cookies 中)}}}__
{{op1{1. 資訊樹}}}
備份檔名 : <<option txtBalaBackupFileName>>
備份主標籤 : <<option txtBalaTreeBody>>
其它備份文章 : <<option txtBalaBackupOthers>>

<<toBalaBackup "NotepadBackup.html">>

{{op1{2. 土芭樂巨集}}}
備份檔名 : <<option txtBalaCoreBackupFileName>>
其它備份文章 : <<option txtBalaCoreBackupOthers>>

<<toBalaCoreBackup "toBalaCoreMacro.html">>

__{{item1{巨集管理}}}__

<<loadTiddlers "label:檢查更新土芭樂巨集" http://tbala.net/x/toBalaMacro.html updates quiet>>







































///%

Linux 系統基礎- 學習筆記本

V1.1 (2010/04/02)

<<tagsTree twcms "" 1 4 index label>>
<<tagsTree lsys0101 "" 1 4 index label>>
<<tagsTree lsys0102 "" 1 4 index label>>
<<tagsTree lsys0103 "" 1 4 index label>>
<<tagsTree lsys0104 "" 1 4 index label>>
<<tagsTree lsys0105 "" 1 4 index label>>
<<tagsTree lsys0106 "" 1 4 index label>>
<<tagsTree lsys0107 "" 1 4 index label>>
<<tagsTree lsys0108 "" 1 4 index label>>
<<tagsTree lsys0109 "" 1 4 index label>>
<<tagsTree KMKConfig "" 1 4 index label>>
<<tagsTree menu "" 1 4 index label>>

 [[首頁]] | [[土芭樂 3.0 - 數位新思路|http://tbala.net/]]  | [[TiddlyWiki 練功坊|http://tiddlywiki.tbala.net/]] | [[匯入文章]]  | [[匯出文章]]  |  &nbsp;&nbsp;<<toBalaRun "Java-CMD.bat" "" "命令提示視窗">>&nbsp;&nbsp;<<newTiddler label:"新增文章">>&nbsp;&nbsp;<<closeAll>>&nbsp;&nbsp;<<saveChanges>> &nbsp;&nbsp;IT 無涯,關機是岸 
//%/
{{item1{老式終端機}}}

[img[img/oldterminal.jpeg]]

''TTY/PTS''
I have been asked the question numerous times of what PTS and TTY mean in Linux regarding terminals. People ask because they may be newer to Linux and learning how to view a process list they may actually see a serial connection, SSH connection, or a telnet connection in the process list that might show something like pts/0, pts/2, tty1, or tty2 in the TTY column. Most processes will just have a question mark in this column but if something is connected to an actual terminal then it will list where it is connected in the TTY column of “ps”.

''TTY Definition:''
Teletypewriter originally and now also means any terminal on Linux/Unix systems. It also means any ''serial port'' on Unix/Linux systems.

''PTS Definition:''
The difference between TTY and PTS is the type of connection to the computer. TTY ports are direct connections to the computer such as a keyboard/mouse or a serial connection to the device. PTS connections are ''SSH connections'' or ''telnet connections''. All of these connections can connect to a shell which will allow you to issue commands to the computer.

[註] PTS 的全名是 pseudo terminal slave
{{item1{設定終端機}}}
''設定 Terminal (關閉 speaker)''
{{{
# setterm -blength 0  -powersave off -blank 0   (暫時)
}}}

{{item1{終端機文字操作介面系統 (Shell)}}}
{{{
- Bash (Bourne-Again shell)
- csh
}}}

''檢視目前所使用的 Shell''
{{{
$ echo $SHELL
/bin/bash
}}}

{{item1{系統內建命令 (System Command)}}}
{{{
- /bin           (mkdir, uname)
- /usr/sbin    (unzip)
- /usr/bin      (useradd)
}}}

''問題 :'' ping 命令在上述那個目錄 ?

{{item1{Home Directory}}}
{{{
- 存放使用者資料
- 應用軟體設定檔 (.xinitrc, ….)
- 自行安裝的應用軟體
}}}

''顯示登入者的 Home Directory''
{{{
# echo ~
/home/tobala
}}}

''問題 : root 的 home Directory ?''

{{item1{環境變數}}}
{{{
- 系統環境變數
- 使用者環境變數 (Bash)
}}}

''顯示系統環境變數''
{{{
# env
           :
MAIL=/var/mail/tobala
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
PWD=/home/tobala
XMODIFIERS=@im=scim
LANG=en_US.UTF-8
HISTCONTROL=ignoreboth
SHLVL=1
HOME=/home/tobala
LOGNAME=tobala
SSH_CONNECTION=192.168.200.1 2544 192.168.200.140 22
LESSOPEN=| /usr/bin/lesspipe %s
DISPLAY=localhost:10.0
GTK_IM_MODULE=scim
LESSCLOSE=/usr/bin/lesspipe %s %s
_=/usr/bin/env
}}}

''顯示系統及使用者環境變數''
{{{
# set | less
BASH=/bin/bash
BASH_ARGC=()
BASH_ARGV=()
BASH_COMPLETION=/etc/bash_completion
BASH_COMPLETION_DIR=/etc/bash_completion.d
BASH_LINENO=()
BASH_SOURCE=()
BASH_VERSINFO=([0]="3" [1]="2" [2]="48" [3]="1" [4]="release" [5]="i486-pc-linux-gnu")
BASH_VERSION='3.2.48(1)-release'
COLUMNS=90
DIRSTACK=()
DISPLAY=localhost:10.0
EUID=1000
GROUPS=()
GTK_IM_MODULE=scim
HISTCONTROL=ignoreboth
HISTFILE=/home/tobala/.bash_history
HISTFILESIZE=500
HISTSIZE=500
HOME=/home/tobala
HOSTNAME=tobalaking
HOSTTYPE=i486
IFS=$' \t\n'
                          :
}}}

<<toBalaNotes "bash">>

///%bash
//%/
本文網址 : http://zh.wikipedia.org/w/index.php?title=Ubuntu&printable=yes

Ubuntu[國際音標:國際音標:/uːˈbuːntuː/(英語);[ùɓúntú](祖魯語)]是一個以桌面應用為主的 Linux 操作系統,其名稱來自非洲南部祖魯語或豪薩語的「ubuntu」一詞(譯為吾幫托或烏班圖),意思是「人性」、「我的存在是因為大家的存在」,是非洲傳統的一種價值觀,相當於中華固有的「仁愛」思想。

Ubuntu 建基於 Debian 發行版和 GNOME 桌面環境,與 Debian 的不同在於它每 6 個月會發佈一個新版本。

普通的桌面應用版可以獲得18個月的支援,標為 ''LTS'' 的桌面應用版可以獲得更長時間的支援。例如,Ubuntu8.04 LTS(代號Hardy Heron),其桌面應用系列可以獲得為期三年的技術支援,伺服器版可以獲得為期五年的技術支援。Ubuntu 的目標在於為一般用戶提供一個最新的、同時又相當穩定的主要由自由軟體構建而成的作業系統。Ubuntu 具有龐大的社群力量,用戶可以方便地從社群獲得幫助。

Kubuntu 與 Xubuntu 是Ubuntu 計畫正式支援的衍生版本,分別將 KDE 與 Xfce 桌面環境帶入 Ubuntu,Edubuntu 是一個針對學校教學環境而設計,試圖讓低齡兒童可以輕鬆學會使用的衍生版本。 

Ubuntu 及其衍生版本至今似乎沒有正式的中文譯名,至少從 Ubuntu 中文網和 Ubuntu 正體中文站的官方網站上來看是這樣。一些中文使用者使用班圖、烏班圖、烏斑兔、烏幫圖等作為非官方譯名,不過並未得到一致認可。

{{op1{歷史與發展過程}}}
Ubuntu 由馬克·舍特爾沃斯創立,其首個版本— 4.10 發佈於 2004 年10 月 20 日,它以 Debian 為開發藍本。與 Debian 穩健的升級策略不同,Ubuntu 每六個月便會發佈一個新版,以便人們及時地獲取和使用新軟體。Ubuntu 的開發目的是為了使個人電腦變得簡單易用,同時也提供針對企業應用的伺服器版本。Ubuntu 的每個新版本均會包含當時最新的 GNOME 桌面環境,通常在GNOME 發佈新版本後一個月內發行。與其他基於 Debian 的 Linux 發行版,如 MEPIS、Xandros、Linspire、Progeny和Libranet等相比,Ubuntu 更接近 Debian 的開發理念,它主要使用自由、開源的軟體,而其他發行版往往會附帶很多閉源的軟體。

Ubuntu 建基於 Debian 的不穩定分支:不論其軟體格式(deb)還是軟體管理與安裝系統(Debian Apt/Synaptic)。Ubuntu 的開發者會把對軟體的修改及時反饋給 Debian 社群,而不是在發佈新版時才宣佈這些修改。事實上,很多 Ubuntu 的開發者同時也是Debian主要軟體的維護者。不過,Debian 與 Ubuntu 的軟體並不一定完全相容,也就是說,將 Debian 的套件安裝在 Ubuntu 上可能會出現相容性問題,反之亦然。

Ubuntu 的運作主要依賴 Canonical 有限公司的支援,同時亦有來自 Linux 社區的熱心人士提供協助。Ubuntu 的開發人員多稱馬克·舍特爾沃斯為 SABDFL(是self-appointed benevolent dictator for life 的縮寫,即自封終生開源碼大老)。在 2005 年 7 月 8 日,馬克·舍特爾沃斯與 Canonica l有限公司宣佈成立 Ubuntu 基金會,並提供 1 千萬美元作為啟始營運資金。成立基金會的目的是為了確保將來 Ubuntu 得以持續開發與獲得支援,但直至 2006 年,此基金會仍未投入運作。馬克·舍特爾沃斯形容此基金會是在 Canonical 有限公司出現財務危機時的緊急營運資金。

目前,Ubuntu 的最新版本為「Jaunty Jackalope」,即在 2009 年4月23日所推出 Ubuntu 9.04(非長期支援版本),使用者可以透過船運服務(shipit)來獲得免費的安裝光碟。前一個LTS版本(Ubuntu 6.06)也有提供免費船運服務,然而其後的 Ubuntu 6.10 版卻沒有提供免費的船運郵寄光碟服務,使用者只可由網站上下載光碟映像檔燒錄並安裝。Ubuntu 6.06 釋出當時,曾有訊息指出往後不會再對非長期支援版提供船運服務,但在 Ubuntu7.04 版推出時,船運服務再度啟動,而此版並非長期支援版。

已於 2008 年 4 月發佈的 Ubuntu 8.04 和 6.06 一樣,都有著 Long Term Support (LTS) 的標籤,代表著這個版本也將獲得更長時間的技術支援(Desktop 版 3 年,Server 版 5 年)。

[img[img/mark-shuttleworth-in-suit.jpg]]

<<toBalaNotes "ubuntu">>
{{item1{Ubuntu 10.04 LucidLynx/ReleaseNotes (請閱讀)}}}
https://wiki.ubuntu.com/LucidLynx/ReleaseNotes

{{item1{Ubuntu 9.04 Desktop Edition}}}
Ubuntu 9.10 新增功能 : http://www.ubuntu.com/getubuntu/releasenotes/910overview

目前每隔半年就推出新版本的 Linux 作業系統 Ubuntu,4 月推出了 9.04 版,它內建最新的 OpenOffice 與 Firefox,並有系統工具Tweak,能輔助系統設定與新增/移除程式。

除了英文輸入之外,由於這套作業系統並沒有內建中文輸入,因此我們還另外安裝了 SCIM 輸入法,以便輸入正體與簡體中文,這個輸入法內建有倉頡、大易、拼音、速成、注音與新酷音等,中文輸入方式多達22種,但是很可惜的沒有嘸蝦米輸入法。

''若檔案系統改用 EXT4,開機速度更快''
在我們實際安裝這套作業系統之前,我們可以下載一張光碟仍裝得下的 ISO 檔,檔案大小僅有 699MB,並將它轉成 CD 或掛載在VM 環境上,在不安裝的情況下直接開機,先執行這套作業系統,或直接在這個環境中選擇安裝。

安裝這個作業系統很簡單,過程中只需要選擇系統語言、安裝磁區、選擇鍵盤類型,並且設定帳號與密碼即可。

如果電腦中已經安裝 Windows 作業系統,而且在選擇「手動」,選擇要安裝的磁碟區之後,Ubuntu 會自動建立多重開機選單,讓使用者可以在開機時選擇想要啟動的作業系統。或者選擇使用整顆硬碟,則會將所有資料刪除,格式化之後再安裝 Ubuntu。

由於這個版本支援 EXT4 的檔案系統,因此在選擇安裝的時候,也可以手動設定將選擇的磁碟區格式化成 EXT4。由於不同的硬體規格,都會影響到開機速度,因此我們使用相同的硬體設備測試,發現用 Live CD 啟動的時間大約為2分鐘,檔案系統為 EXT3 的開機時間為 51 秒,如果選擇 EXT4 格式,開機時間可縮短為35秒,在速度上確實改善不少。

假如你使用 Ubuntu 如 8.04 或 8.10,也可以透過更新管理員,即可直接下載相關檔案、升級。

另外這個系統還有個 USB 啟動碟產生器,只要電腦中有 Ubuntu 9.04 的映像檔或者安裝光碟,即可透過這個啟動碟產生器,將USB 隨身碟設定成開機隨身碟,只要將這個裝置插入支援 USB 開機的電腦中,同樣可以執行這個作業系統。

''內建工具能簡化系統與應用程式管理''
要安裝這個作業系統的應用程式或套件,我們可網路手動下載、安裝,或透過 Synaptic 套件管理程式來下載,不過必須先知道套件名稱。另一個可讓你修改細部設定的系統工具是 Ubuntu Tweak,它允許使用者自行調整系統的隱藏設定、清除不需要的套件、安裝應用程式,以及開啟檔案的預設程式。

在 Tweak 的應用程式選項中,我們可以看到目前已經安裝哪些應用程式,在網路上提供有哪些程式可以安裝,而且還很貼心地附有每個應用程式的簡單說明。要安裝程式,只需要勾選、確定之後,就會透過網路下載更新檔案,並且安裝。安裝好的套件安裝檔案,同樣也可透過Tweak清理,節省硬碟空間。

例如 Adobe Reader for Linux 就必須從 Adobe 網站下載 RPM 檔,並且手動安裝,而一些套件程式如管理桌面特效的 Compiz,就要透過Synaptic 套件管理程式下載安裝。

另外,透過 Tweak 這個程式,使用者也可以管理檔案類型、直接修改檔案預設開啟的應用程式,而且還按照音訊、文字、圖片與視訊等分類,在修改預設開啟的應用程式時很方便。

[img[img/ubuntu9.04/udesk01.jpg]]
使用 Tweak 來新增、移除程式非常方便,只需要勾選要安裝的應用程式並且套用,就會從網路下載、安裝。

''內建 Pidgin 可登入多種即時通訊網路,也能額外安裝 Skype''
除了文書處理之外,一般辦公室最常用到的程式,莫過於網頁瀏覽、MSN 與Skype。Ubuntu 內建了 Firefox;用來網路交談的MSN,在 Ubuntu 上的替代品是:Pidgin。裝上 Skype for Linux 使用也沒有太大問題。

Pidgin 這套軟體支援 MSN、Yahoo、Google Talk,以及 ICQ 等 16 種即時通訊協定,我們不需要另外安裝軟體,就能使用原本的帳號,與廠商或者客戶文字交談。

[img[img/ubuntu9.04/udesk02.jpg]]

內建的 Pidgin 支援MSN、Yahoo 與 Google Talk 等協定,可同時使用多種 IM 帳號登入。

另外還有個很貼心的提示,當我們要關閉對話視窗,卻有訊息未讀取時,這個軟體會提示有未讀取訊息,並確認是否關閉對話視窗。
實際使用之後發現,Pidgin 這套軟體雖然支援多種即時通訊協定,可以文字交談之外,也可以傳送檔案,不過很可惜並沒有視訊通話,以及共用資料夾等其他附加功能。另一種常用的通訊程式 Skype,在這個作業系統上也可以安裝,且使用介面與Windows接近,使用者不需要花時間學習適應。

在這套作業系統上也內建一套與O utlook 相似的Evolution郵件軟體,可收發電子郵件之外,也可儲存聯絡資訊、行事曆、備忘錄與工作清單。

使用Evolution郵件之後,我們發現與 Outlook 接近,這個軟體也可以在收件夾中新增資料夾,將收到的電子郵件分類,方便管理。而聯絡人與行事曆,也可以透過 Pine、Netscape、Elm 與 iCalender 等檔案格式匯入的方式,從舊環境將資料轉移到Evolution郵件。

''提升周邊設備支援,並可連結共用資料夾''
Ubuntu 9.04 還有許多輔助工具值得使用,例如我們可以在上下面板中,加入系統監控程式、CPU頻率調整監控程式、螢幕亮度調整,甚至使用者切換快捷鍵等。要使用這些應用程式,只要在面板中點一下,就能快速開啟、顯示這些資訊或修改設定。

而且這個版本還新整合了通知系統功能,接收到新訊息、郵件等會在螢幕上顯示,就像在 Windows 上的 MSN,接收到新訊息時,會有提示視窗,能有效提醒使用者,以免忽略重要資訊。

在公司內部環境的使用上,要新增印表機,只需要選擇系統管理的印表機設定,就能將網域內部可以連接到的所有列印設備顯示出來,我們只需要選擇型號,Ubuntu 就會自動連上網路搜尋適當的應用程式,並且安裝,例如HP與Richo等印表機與影印設備都支援。
另外,要連接到 FTP 或者 Windows 共用資料夾也很簡單,由於 Ubuntu 已經內建 SMB通 訊協定,所以都能順利連結 FTP伺服器與其他電腦所分享的共用資料夾。

如果電腦安裝 Windows 與 Ubuntu 雙系統,你還可使用 Wine 模擬器,在不開啟 Windows 作業系統的情況下,直接執行Windows 內的應用程式,對正在使用 Ubuntu 作業系統,卻需要使用 Windows 應用程式,幫助很大。文⊙林柏凱

[img[img/ubuntu9.04/udesk03.jpg]]
這個版本內建支援多種通訊協定的即時通訊軟體 Pidgin、系統管理工具 Tweak,並加入能避免使用者遺漏重要訊息的系統通知功能。

<<toBalaNotes "ubuntu904">>

///%ubuntu9
//%/

///%ubuntu
//%/

///%ubuntu904
//%/
''參考文章''
1. Learn Linux, 101: The Linux command line
http://www.ibm.com/developerworks/linux/library/l-lpic1-v3-103-1/index.html
2. Shell 設計入門
http://linux.tnc.edu.tw/techdoc/shell/book1.html

Bash 官方網站 : http://www.gnu.org/software/bash/#TOCintroduction

{{item1{認識 Bash shell}}}
Bash is the shell, or command language interpreter, that will appear in the GNU operating system. Bash is an sh-compatible shell that incorporates useful features from the Korn shell (ksh) and C shell (csh). It is intended to conform to the IEEE POSIX P1003.2/ISO 9945.2 Shell and Tools standard. It offers functional improvements over ''sh for both programming and interactive use''. In addition, most sh scripts can be run by Bash without modification.

''The improvements offered by BASH include:''
{{{
* Command line editing
* Unlimited size command history
* Job Control
* Shell Functions and Aliases
* Indexed arrays of unlimited size
* Integer arithmetic in any base from two to sixty-four 
}}}
The manual is available online at http://www.gnu.org/software/bash/manual/.

The maintainer also has a [[bash page|http://cnswww.cns.cwru.edu/~chet/bash/bashtop.html]] which includes [[Frequently-Asked-Questions|ftp://ftp.cwru.edu/pub/bash/FAQ]].

{{op1{Bash 版本代號}}}
{{{
# bash --version
GNU bash, version 3.2.48(1)-release (i486-pc-linux-gnu)
Copyright (C) 2007 Free Software Foundation, Inc.
}}}

{{op1{啟動 Bash}}}
{{{
# echo  $SHLVL
1

# bash

# echo  $SHLVL
2
}}}

{{op1{結束 Bash}}}
{{{
# exit
}}}
<<toBalaNotes "bash">>

{{item1{Bourne Shell Builtins}}}
網址 : http://www.network-theory.co.uk/docs/bashref/BourneShellBuiltins.html

''內建命令如下''
break, cd, continue, eval, exec, exit, export, getopts, hash, pwd, readonly, return, shift, test, times, trap, umask, unset

''是否為內定命令 ? (使用 type 命令)''
{{{
$ type cd
cd is a shell builtin
$ type ping
ping is /bin/ping
}}}

{{item1{內建 (Builtins) 與外部命令同名}}}

''1. 檢視 /bin/echo 外部命令手冊, 在手冊中有看到 &#45;&#45;version 這參數''
{{{
$ man /bin/echo
ECHO(1)                          User Commands                         ECHO(1)

NAME
       echo - display a line of text

SYNOPSIS
       echo [SHORT-OPTION]... [STRING]...
       echo LONG-OPTION

DESCRIPTION
       Echo the STRING(s) to standard output.

       -n     do not output the trailing newline

       -e     enable interpretation of backslash escapes

       -E     disable interpretation of backslash escapes (default)

       --help display this help and exit

       --version
              output version information and exit

 Manual page echo(1) line 1
}}}

''2. 執行 /bin/echo 命令''
{{{
$ /bin/echo --version
echo (GNU coreutils) 7.4
Copyright (C) 2009 Free Software Foundation, Inc.
許可證 GPLv3+: GNU GPL 版本 3 或更新 <http://gnu.org/licenses/gpl.html>.
這是自由軟體:您可自由修改或散佈。
在法律准許範圍內不負帶保證。

由 Brian Fox 和 Chet Ramey 編寫。
}}}

''3. 執行內建 echo 命令''

由以下的執行結果, 得知直接在 bash prompt 中執行 echo 命令, 是沒提供  &#45;&#45;version 這參數, 那在 Bash Script 程式中, 均是執行內建命令, 除非使用完整目錄 (/bin/echo) 來執行外部命令
{{{
$ echo --version
--version
}}}

''[註]''  A builtin may be a synonym to a system command of the same name, but Bash reimplements it internally. For example, the ''Bash echo'' command is not the same as ''/bin/echo'', although their behavior is almost identical. 

{{item1{Disable Linux builtin command using enable command.}}}
The step by step Linux command example below show how to disable Linux builtin command using the enable command.  By disabling the Linux builtin command, it allow you to execute command that using same name as Linux builtin command to be execute without specifying the full pathname to the binary file of that command.  The step by step command example below use pwd command as an example to show the output when we use the pwd command from Linux built command and after that we disable the Linux builtin command in this case pwd command and then execute the pwd command from the disk command (not builtin command).

''Disable builtin command''

1. To show list of builtin command that you can use on your Linux system, execute enable -a command.
{{{
[root@fedora11 ~]# enable -a
...
enable pwd
...
}}}
 
2.  Use the which command to check the same pwd command also available on your Linux system (not builtin command).
{{{
[root@fedora11 ~]# which pwd
/bin/pwd
}}}
3.  Execute Linux builtin command.  the example below we execute the pwd command to display help file.
{{{
[root@fedora11 ~]# pwd --help
-bash: pwd: --: invalid option
pwd: usage: pwd [-LP]
}}}
4.  Now disable Linux builtin command, in this example we disable pwd command the builtin one :-), use the enable command with -n option and then the builtin command name that we want to disable.
{{{
[root@fedora11 ~]# enable -n pwd
}}}

5.  To show disable builtin command, execute enable command with -n option, as show on example below.
{{{
[root@fedora11 ~]# enable -n
enable -n pwd
}}}
6.  To verify and and to prove that we already disable Linux builtin command, try execute pwd command again .... this time we expect output from the pwd command is different because we execute the disk command.
{{{
[root@fedora11 ~]# pwd --help

Usage: pwd [OPTION]...

Print the full filename of the current working directory.

  -L, --logical   use PWD from environment, even if it contains symlinks
  -P, --physical  avoid all symlinks
      --help     display this help and exit
      --version  output version information and exit

NOTE: your shell may have its own version of pwd, which usually supersedes

the version described here.  Please refer to your shell's documentation
for details about the options it supports.

Report pwd bugs to bug-coreutils@gnu.org
GNU coreutils home page: <http://www.gnu.org/software/coreutils/>
General help using GNU software: <http://www.gnu.org/gethelp/>
Report pwd translation bugs to <http://translationproject.org/team/>
}}}

<<toBalaNotes "buildin">>

///%bash
//%/

///%buildin
//%/
{{item1{安裝 OpenSSH}}}
{{{
$ sudo apt-get install ssh
}}}

{{item1{連接 openssh-server}}}
本文 : http://tonychou.posterous.com/ubuntu-ssh

好,當我們安裝好,基本上就可以用 putty 來用遠端登入了,當然是有帳密的人就可以登入啦,但是我們都瞭解,這樣子是不安全的,基本上我們要限定連入 IP 還有改變 PORT,如此才會比較安全。

接下來我們一樣可以來檢查是否有執行這個 ssh-server,輸入以下指令
{{{
ps aux | grep ssh
}}}

{{item1{設定 ssh_config 內容}}}
我們若在主機上,就會有二條訊息,一是 root,一是你登入的名稱。若是用遠端登入,就會有遠端登入的名稱,訊息就會多出2~3條,那是正常的,接下來我們進入 ssh 的 config 檔案。
{{{
sudo nano /etc/ssh/sshd_config
}}}
找一下,看到這行,可以做更改,但事實上,ubuntu 本身就有限制 root 的登入,因此是沒有特別的意義,但還是可以修改,以防萬一
{{{
#PermitRootLogin Yes 
改成
PermitRootLogin no
}}}

再來找到
{{{
# What ports, IPs and protocols we listen for (約第4、5行)
Port 22
}}}

可將預設的port改成系統未在使用的port,因為系統預設都會有一些連接 port,例如:ftp 是 port 21、web 是 port 80、 smtp 是port 25、ssh 是 port 22、telnet 是 port 23 等等,那你要怎麼知道哪些被使用呢?鍵入下列的指令吧。
(port 的內容相當多,在一個區段內找一個數字,只要在 services 當中沒出現的即可)
{{{
sudo less /etc/services
}}}

例如:91 這個port系統沒有使用,那你就將 22 改成 91,那這樣在連 ssh 時就必須將 port 改成 91,若維持 22 是連不進去的。

{{item1{限制 IP 登入}}}
再來,我們要修改可以登入這台主機的 ip,否則任可一個 ip 都可以利用帳號登入,這是基本的防護。
{{{
sudo vim /etc/hosts.allow
}}}
在最下方加入
{{{
sshd:xxx.xxx.xxx.xxx :allow
}}}
xxx 就是指你的 ip 位置,包含你遠端要登入的 ip (一般 ADSL 浮動 ip 則不適用,此方法只適用固定 IP)。若你是 ADSL,但又想要登入主機上工作修改,那可以到中華電信的固定 IP 申請頁面,線上申請後可以馬上使用,雖然不是真的固定 IP,但是可以讓你工作方便才是最重要的。

{{item1{拒絕所有 IP 登入}}}
當你允許了你指定的 IP 可以登入,那其他的浮動 IP 就不讓他們登入了,避免不必要的麻煩和攻擊
{{{
sudo nano /etc/hosts.deny
}}}
加入 sshd:all:deny

如此一來,除了你允許的 IP 之外,其他的浮動 IP 就連不進來
{{{
sudo /etc/init.d/ssh stop
sudo /etc/init.d/ssh start
}}}
一樣修改完成後,要重新啟動喔!

''說明:''但是不同於 apache2 一樣可以 restart,在網路上的資料是寫 restart,我試過不行,後來我看過 config 檔案,ssh 這裡只能stop 跟 start,無論你所使用的程式是否支援 restart,stop 跟 start 是一定會有的。
<<toBalaNotes "ssh">>


///%ssh
//%/
When upgrading an Ubuntu server to 8.04 LTS, you should use the new and improved server upgrade system. Use the following steps to activate this upgrade process:
{{{
1. Install the “update-manager-core” package. Dependencies include python-apt, python-gnupginterface and python2.4-apt.
2. Run the command “sudo do-release-upgrade” in a terminal window
}}}
''參考網站''
1. 如何製作 Ubuntu Live USB
http://gordon168.tw/?p=323
2. Ubuntu Desktop 12.04 LTS security configuration guide  (很重要)
http://www.rationallyparanoid.com/articles/ubuntu-12-lts-security.html
3. Ubuntu 12.04 Server – How to Install a GUI (重要)
http://complete-concrete-concise.com/ubuntu-2/ubuntu-12-04-server/ubuntu-12-04-server-how-to-install-a-gui
4. 5 Best Practices to Secure and Protect SSH Server'' (一定要做, 否則會中毒)''
http://www.tecmint.com/5-best-practices-to-secure-and-protect-ssh-server/

{{item1{下載 Ubuntu Server 安裝光碟}}}

正式網址 : http://www.ubuntulinux.org/getubuntu/download-server
Ubuntu Daily Build 網址 : http://cdimage.ubuntu.com/

{{item1{開始安裝 Ubuntu Server 10.04}}}

{{op1{1. 選擇語系}}}

[img[img/ubuntu10.4/server/server_install01.png]]

{{op1{2.  選擇安裝模式 (安裝 Ubuntu 伺服器)}}}

[img[img/ubuntu10.4/server/server_install02.png]]

{{op1{3. 選擇鍵盤格式 (選擇 "否")}}}

[img[img/ubuntu10.4/server/server_install03.png]]

[img[img/ubuntu10.4/server/server_install04.png]]

[img[img/ubuntu10.4/server/server_install05.png]]

{{op1{4. 設定主機名稱}}}

[img[img/ubuntu10.4/server/server_install06.png]]

{{op1{5. 設定時區}}}

[img[img/ubuntu10.4/server/server_install07.png]]

{{op1{6. 硬碟設定}}}

[img[img/ubuntu10.4/server/server_install08.png]]

[img[img/ubuntu10.4/server/server_install09.png]]

[img[img/ubuntu10.4/server/server_install10.png]]

{{op1{7. 設定使用者帳號 (完整名稱及登入名稱)}}}

[img[img/ubuntu10.4/server/server_install11.png]]

[img[img/ubuntu10.4/server/server_install12.png]]

{{op1{8. 設定使用者帳號的密碼}}}

[img[img/ubuntu10.4/server/server_install13.png]]

[img[img/ubuntu10.4/server/server_install14.png]]


{{op1{9. 設定家目錄 (選擇 "否", 不要加密)}}}

[img[img/ubuntu10.4/server/server_install15.png]]

{{op1{10. 設定 Proxy Server (不需設定)}}}

[img[img/ubuntu10.4/server/server_install16.png]]

{{op1{11. 系統自動更新 (選擇 "不自動更新")}}}

[img[img/ubuntu10.4/server/server_install17.png]]

{{op1{12. 選擇所需安裝的網路服務}}}

[img[img/ubuntu10.4/server/server_install18.png]]

{{op1{13. 設定 GRUB}}}

[img[img/ubuntu10.4/server/server_install19.png]]

{{op1{14. 結束安裝}}}

[img[img/ubuntu10.4/server/server_install20.png]]

<<toBalaNotes "server">>
{{item1{Ubuntu 桌面版本安裝}}}
請參考此網址 : http://www.psychocats.net/ubuntu/installing

<<toBalaNotes "desktop">>



///%server
//%/

///%desktop
//%/
{{item1{VMware Workstation 網路設定}}}

[img[img/vmware/VMNet01.png]]

在上圖中共有四類網路架構可使用

''1. Bridge''
可挑選主戰機的任一網卡, 作為橋接介面, 這片網卡必須勾選 VMware Bridge Protocol, 如下圖 :

[img[img/vmware/VMNet01-1.png]]

''2. NAT (提供 NAT 及 DHCP 服務)''
在這網路中的虛擬主機, 可透過 VMnet8 的 NAT 服務上網

''3. HOST Only (提供 DHCP 服務)''
在這網路中的虛擬主機, 無法上網, 可與主戰機的 VMnet1 網卡互通

''4. Custom (沒有提供任何網路服務)''
網路中的虛擬主機, 可互通, 但無法與主戰機互通

{{item1{Host Only 網路設定}}}

[img[img/vmware/VMNet02.png]]

上圖中有提供 DHCP 服務, 請看下圖中的設定

[img[img/vmware/VMNet03.png]]

上圖中的 IP 配置範圍 192.168.233.128 - 254, 請將 ''254'' 改成 ''250'', 這時 DHCP 服務會使用 ''192.168.233.250'' 這 IP 位址, 來配置 IP 位址給 Client, ''所以 192.168.233.250 這位址是無法被虛擬主機使用''

{{item1{NAT 網路設定}}}

[img[img/vmware/VMNet04.png]]

在下圖中可得知 NAT 服務是使用 192.168.56.2 這 IP 位址

[img[img/vmware/VMNet05.png]]
<<toBalaNotes "vmnet">>



///%vmnet
//%/
<<forEachTiddler 
 where
   'tiddler.tags.contains("toBalaMacro")'
>>
{{item1{mkdir}}}
{{{
# mkdir  -p  ~/dir1/dir2/dir3
}}}

''-p  no error if existing, make parent directories as needed''

{{item1{rmdir 刪除『空』的目錄}}}
{{{
# rmdir -p  dir1/dir2/dir3
}}}

''[注意]'' 目錄內容必須是空的, 才能執行上式

''[問題]'' mkdir {1,2}_{a,b,c} 這命令會產生幾個目錄 ?

{{item1{cd}}}
{{{
# cd ~
}}}

{{item1{mv}}}
{{{
# mv  bbb  aaa       
}}}

{{item1{rm}}}
{{{
# rm -R  dir1
}}}

By default, rm does not remove directories.  Use the ''-r or -R'' option to remove each listed directory, too, along with all of its contents.

{{item1{touch (產生新檔案)}}}
{{{
# touch abc
}}}

''[問題]'' touch {x,y,z}_{a,b,c} 這命令會產生幾個檔案 ?

{{item1{cp}}}
{{{
# cp -Rp  src  src2
}}}

''-R''  遞迴
''-p''  保留檔案權限資訊

{{item1{tree : 快速列出樹狀目錄結構清單}}}
在 Ubuntu Server 10.04 系統並沒安裝此工具, 請執行以下命令, 安裝 tree
{{{
$ sudo apt-get install tree
}}}

''顯示家目錄內容''
{{{
$ tree
.
├── :
├── bin
│ ├── dispdev
│ ├── dos
│ ├── ipscan
│ ├── makeu.sh
│ ├── null
│ ├── scr.sh
│ └── users.txt
├── kmdepot
│ └── cgi-bin
│     └── test.cgi
└── oncloud9_0.1
    ├── bin
    │ ├── cgi-bin
    │ ├── cloudclass.sh
    │ ├── cloudstudent.sh
    │ ├── cloudtest.sh
    │ ├── conf2env.sh
    │ ├── gplv2.txt
    │ ├── makeoncloud9.sh
    │ ├── mkindex.sh
    │ └── setupCGI.sh
    ├── conf
    │ └── oncloud9.conf
    └── oc9.sh

9 directories, 17 files
}}}

<<toBalaNotes "file">>

///%file
//%/
''參考文章''
1. Ubuntu 10.10 (Maverick Meerkat)正式版釋出,效率大改進更易用
http://yblog.org/archive/index.php/11534

{{item1{安裝 gcin}}}

[img[img/ubuntu10.4/Desktop/gcin00.png]]

{{item1{修改鍵盤輸入法系統}}}
系統>管理>語言支援>修改鍵盤輸入法系統>從IBus改成gcin

[img[img/ubuntu10.4/Desktop/gcin01.png]]

{{item1{選擇輸入法}}}
系統>偏好設定>gcin 輸入法設定>內定輸入法 & 開啟/關閉

[img[img/ubuntu10.4/Desktop/gcin02.png]]
''[註]'' 嘸蝦米輸入法可選擇, 卻無法使用, 因嘸蝦米輸入法要花錢買, 如要自行安裝, 請參考這 [[網址|http://www.inote.tw/2009/05/ubuntugcin.html]]

<<toBalaNotes "gcin">>

///%gcin
//%/
''參考文章''
1. Ubuntu User Management
https://help.ubuntu.com/8.04/serverguide/C/user-management.html

{{item1{建立帳號}}}
{{{
# sudo useradd  -m  -s /bin/bash xman01
}}}

''useradd 實際動作''
{{{
* 在 /etc/passwd 裡面建立一行與帳號相關的資料,包括建立 UID/GID/家目錄等;
* 在 /etc/shadow 裡面將此帳號的密碼相關參數填入,但是尚未有密碼;
* 在 /etc/group 裡面加入一個與帳號名稱一模一樣的群組名稱;
* 在 /home 底下建立一個與帳號同名的目錄作為使用者家目錄,且權限為 700
}}}

''[注意]'' 沒有 -m 參數, 在 /etc/passwd 檔案中, Home Directory 還是設為 /home/xman01, 但是 /home/xman01 目錄並沒有產生, 如使用此帳號登入, 因沒有 /home/xman01 目錄, 所以內定在 / 目錄, 但卻無法產生檔案, 因權限不夠 

''useradd 的簡易手冊''
{{{
Usage: useradd [options] LOGIN

Options:
  -b, --base-dir BASE_DIR       base directory for the new user account
                                home directory
  -c, --comment COMMENT         set the GECOS field for the new user account
  -d, --home-dir HOME_DIR       home directory for the new user account
  -D, --defaults                print or save modified default useradd
                                configuration
  -e, --expiredate EXPIRE_DATE  set account expiration date to EXPIRE_DATE
  -f, --inactive INACTIVE       set password inactive after expiration
                                to INACTIVE
  -g, --gid GROUP               force use GROUP for the new user account
  -G, --groups GROUPS           list of supplementary groups for the new
                                user account
  -h, --help                    display this help message and exit
  -k, --skel SKEL_DIR           specify an alternative skel directory
  -K, --key KEY=VALUE           overrides /etc/login.defs defaults
  -l,                           do not add the user to the lastlog and
                                faillog databases
  -m, --create-home             create home directory for the new user
                                account
  -N, --no-user-group           do not create a group with the same name as
                                the user
  -o, --non-unique              allow create user with duplicate
                                (non-unique) UID
  -p, --password PASSWORD       use encrypted password for the new user
                                account
  -r, --system                  create a system account
  -s, --shell SHELL             the login shell for the new user account
  -u, --uid UID                 force use the UID for the new user account
  -U, --user-group              create a group with the same name as the user
}}}

{{item1{檢視帳號資訊}}}

''檢視 xman01 的家目錄''
{{{
$ ls -al /home
總計 16
drwxr-xr-x  4 root   root   4096 2009-08-09 22:13 .
drwxr-xr-x 21 root   root   4096 2009-06-16 14:04 ..
drwxr-xr-x  4 tobala tobala 4096 2009-08-09 21:53 tobala
drwxr-xr-x  2 xman01 xman01 4096 2009-08-09 22:13 xman01
}}}

''檢視帳號 uid,gid 及所屬群組''
{{{
$ id xman01
uid=1001(xman01) gid=1001(xman01) 群組=1001(xman01)
}}}

''檢視系統帳號檔''
{{{
$ grep xman01 /etc/passwd
xman01:x:1001:1001::/home/xman01:/bin/sh
}}}

{{item1{設定密碼}}}
新帳號密碼沒設, 是無法登入.
{{{
$ sudo passwd xman01
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
}}}

{{item1{新帳號登入}}}

使用第二終端機登入 (ALT+F2)
{{{
Using username "xman01".
xman01@192.168.200.5's password:
Linux tobalaking 2.6.28-11-server #42-Ubuntu SMP Fri Apr 17 02:48:10 UTC 2009 i686

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

To access official Ubuntu documentation, please visit:
http://help.ubuntu.com/
/usr/bin/X11/xauth:  creating new authority file /home/xman01/.Xauthority
$ echo $PS1
$
$ echo $SHELL
/bin/sh
$ exit    離開 sh 程式
}}}

{{item1{刪除帳號}}}
{{{
# userdel  -r  xman01     (包括移除 Home 目錄)
}}}

<<toBalaNotes "basic">>

''usermod 的簡易手冊''
{{{
$ usermod --help
Usage: usermod [options] LOGIN

Options:
  -c, --comment COMMENT         new value of the GECOS field
  -d, --home HOME_DIR           new home directory for the user account
  -e, --expiredate EXPIRE_DATE  set account expiration date to EXPIRE_DATE
  -f, --inactive INACTIVE       set password inactive after expiration to INACTIVE
  -g, --gid GROUP               force use GROUP as new primary group
  -G, --groups GROUPS           new list of supplementary GROUPS
  -a, --append                  append the user to the supplemental GROUPS
                                mentioned by the -G option without removing
                                him/her from other groups
  -h, --help                    display this help message and exit
  -l, --login NEW_LOGIN         new value of the login name
  -L, --lock                    lock the user account
  -m, --move-home               move contents of the home directory to the
                                new location (use only with -d)
  -o, --non-unique              allow using duplicate (non-unique) UID
  -p, --password PASSWORD       use encrypted password for the new password
  -s, --shell SHELL             new login shell for the user account
  -u, --uid UID                 new UID for the user account
  -U, --unlock                  unlock the user account
  -Z, --selinux-user            new SELinux user mapping for the user account
}}}

{{item1{帳號更名}}}

''1. 更改家目錄''
{{{
$ sudo usermod -d /home/storm xman01     (只是修改 /etc/passwd 的家目錄路徑)

student@US1041OC9:~$ grep xman01 /etc/passwd
xman01:x:1001:1001::/home/storm:/bin/bash

$ ls -al /home
總計 16
drwxr-xr-x  4 root    root    4096 2010-09-22 12:58 .
drwxr-xr-x 22 root    root    4096 2010-09-19 18:59 ..
drwxr-xr-x  6 student student 4096 2010-09-20 12:19 student
drwxr-xr-x  2 xman01  xman01  4096 2010-09-22 12:58 xman01

student@US1041OC9:~$ cd /home
student@US1041OC9:/home$ sudo cp -Rp xman01 storm     (自行產生 storm 家目錄)
student@US1041OC9:/home$ ls -al
總計 20
drwxr-xr-x  5 root    root    4096 2010-09-22 13:19 .
drwxr-xr-x 22 root    root    4096 2010-09-19 18:59 ..
drwxr-xr-x  2 xman01  xman01  4096 2010-09-22 12:58 storm
drwxr-xr-x  6 student student 4096 2010-09-20 12:19 student
drwxr-xr-x  2 xman01  xman01  4096 2010-09-22 12:58 xman01
}}}

''2. 更改帳號名稱''
{{{
student@US1041OC9:/home$ sudo usermod -l storm xman01
usermod: user xman01 is currently logged in

student@US1041OC9:/home$ sudo usermod -l storm xman01  (只會更改 /etc/passwd, 不會更改 /etc/group)

student@US1041OC9:/home$ tail -n 5 /etc/passwd
syslog:x:101:103::/home/syslog:/bin/false
sshd:x:102:65534::/var/run/sshd:/usr/sbin/nologin
landscape:x:103:108::/var/lib/landscape:/bin/false
student:x:1000:1000:student,,,:/home/student:/bin/bash
storm:x:1001:1001::/home/storm:/bin/bash

$ tail -n 5 /etc/group   
lpadmin:x:109:student
sambashare:x:110:student
admin:x:111:student
ssl-cert:x:112:
xman01:x:1001:                       (名稱沒有被修改)
}}}

''3. 更改主要群組''
{{{
$ sudo groupmod -n storm xman01                            (使用 groupmod 將 xman01 名稱改成 storm)

student@US1041OC9:/home$ tail -n 5 /etc/group
lpadmin:x:109:student
sambashare:x:110:student
admin:x:111:student
ssl-cert:x:112:
storm:x:1001:

student@US1041OC9:/home$ id storm                      (確認 storm 帳號的主要群組變為 storm)
uid=1001(storm) gid=1001(storm) 群組=1001(storm)
}}}

''快速更名步驟''
{{{
$ sudo usermod -l bobe -d /home/bobe -m -g bobe storm
usermod: group 'bobe' does not exist

$ sudo usermod -l bobe -d /home/bobe -m storm
$ sudo groupmod -n bobe storm
}}}

<<toBalaNotes "2">>
{{item1{Ubuntu 帳號管理命令}}}
在 Ubuntu 系統, 帳號與群組管理使用 ''adduser'', ''deluser'', ''addgroup'' 及 ''delgroup'' 這幾個命令, 在使用上較標準命令 (useradd, groupadd,..) 好用, 功能也較強大.

@@color:blue;
The ''adduser'' and ''addgroup'' are ''friendlier front ends'' to the low level tools like ''useradd'', ''groupadd'' and ''usermod'' programs, by default  choosing Debian  policy conformant UID and GID values, creating a home directory with skeletal configuration, running a custom script,  and  other  features. 
@@

{{op1{Adding and Deleting Users}}}

The process for managing local users and groups is straight forward and differs very little from most other GNU/Linux operating systems. Ubuntu and other Debian based distributions, encourage the use of the "adduser" package for account management.

''To add a user account'', use the following syntax, and follow the prompts to give the account a password and identifiable characteristics such as a full name, phone number, etc.
{{{
$ sudo adduser username
}}}

''To delete a user account and its primary group'', use the following syntax:
{{{
$ sudo deluser username
}}}

Deleting an account does not remove their respective home folder. It is up to you whether or not you wish to delete the folder manually or keep it according to your desired retention policies.

Remember, any user added later on with the same UID/GID as the previous owner will now have access to this folder if you have not taken the necessary precautions.

You may want to change these UID/GID values to something more appropriate, such as the root account, and perhaps even relocate the folder to avoid future conflicts:
{{{
$ sudo chown -R root:root /home/username/
$ sudo mkdir /home/archived_users/
$ sudo mv /home/username /home/archived_users/
}}}
    
''To temporarily lock or unlock a user account'', use the following syntax, respectively:
{{{
$ sudo passwd -l username
$ sudo passwd -u username
}}}
    
''To add or delete a personalized group'', use the following syntax, respectively:
{{{
$ sudo addgroup groupname
$ sudo delgroup groupname
}}}

''To add a user to a group'', use the following syntax:
{{{
$ sudo adduser username groupname
}}}
''adduser 簡易說明''
{{{

ADDUSER(8)                                                          ADDUSER(8)

NAME
       adduser, addgroup - add a user or group to the system

SYNOPSIS
       adduser  [options]  [--home  DIR]  [--shell  SHELL]  [--no-create-home]
       [--uid ID] [--firstuid ID] [--lastuid ID] [--ingroup GROUP | --gid  ID]
       [--disabled-password]      [--disabled-login]      [--gecos      GECOS]
       [--add_extra_groups] [--encrypt-home] user

       adduser --system [options] [--home DIR] [--shell  SHELL]  [--no-create-
       home]  [--uid  ID]  [--group | --ingroup GROUP | --gid ID] [--disabled-
       password] [--disabled-login] [--gecos GECOS] user

       addgroup [options] [--gid ID] group

       addgroup --system [options] [--gid ID] group

       adduser [options] user group

   COMMON OPTIONS
       [--quiet] [--debug] [--force-badname] [--help|-h]  [--version]  [--conf
       FILE]

DESCRIPTION
       adduser  and  addgroup  add users and groups to the system according to
       command    line    options    and    configuration    information    in
       /etc/adduser.conf.   They  are  friendlier  front ends to the low level
       tools like useradd, groupadd and usermod programs, by default  choosing
       Debian  policy conformant UID and GID values, creating a home directory
       with skeletal configuration, running a custom script,  and  other  fea‐
       tures.  adduser and addgroup can be run in one of five modes:

   Add a normal user
       If  called  with  one  non-option  argument and without the --system or
       --group options, adduser will add a normal user.

       adduser will choose the first available UID from  the  range  specified
       for  normal users in the configuration file.  The UID can be overridden
       with the --uid option.

       The range specified in the configuration file may  be  overridden  with
       the --firstuid and --lastuid options.

       By  default,  each  user  in  Debian GNU/Linux is given a corresponding
       group with the same name.  Usergroups allow group writable  directories
       to  be  easily  maintained  by placing the appropriate users in the new
       group, setting the set-group-ID bit in the directory, and ensuring that
       all  users use a umask of 002.  If this option is turned off by setting
       USERGROUPS to no, all users' GIDs are set to USERS_GID.  Users' primary
       groups  can  also be overridden from the command line with the --gid or
       --ingroup options to set the group by id or name, respectively.   Also,
       users can be added to one or more groups defined in adduser.conf either
       by setting  ADD_EXTRA_GROUPS  to  1  in  adduser.conf,  or  by  passing
       --add_extra_groups on the commandline.

       adduser  will create a home directory subject to DHOME, GROUPHOMES, and
       LETTERHOMES.  The home directory can be  overridden  from  the  command
       line with the --home option, and the shell with the --shell option. The
       home directory's set-group-ID bit is set if USERGROUPS is yes  so  that
       any  files  created  in the user's home directory will have the correct
       group.

       adduser will copy files from SKEL into the home  directory  and  prompt
       for  finger  (gecos) information and a password.  The gecos may also be
       set with the --gecos option.  With  the  --disabled-login  option,  the
       account  will  be created but will be disabled until a password is set.
       The --disabled-password option will not set a password,  but  login  is
       still possible (for example with SSH RSA keys).  To set up an encrypted
       home directory for the new user, add the  --encrypt-home  option.   For
       more information, refer to the -b option of ecryptfs-setup-private(1).

       If  the  file /usr/local/sbin/adduser.local exists, it will be executed
       after the user account has been set up in order to do any local  setup.
       The arguments passed to adduser.local are:
       username uid gid home-directory
       The  environment  variable  VERBOSE  is  set according to the following
       rule:

       0 if --quiet is specified

       1 if neither --quiet nor --debug is specified

       2 if --debug is specified

              (The same applies to the variable DEBUG, but DEBUG is deprecated
              and will be removed in a later version of adduser.)


   Add a system user
       If called with one non-option argument and the --system option, adduser
       will add a system user. If a user with the same name already exists  in
       the  system uid range (or, if the uid is specified, if a user with that
       uid already exists), adduser will exit with a warning. This warning can
       be suppressed by adding "--quiet".

       adduser  will  choose  the first available UID from the range specified
       for system  users  in  the  configuration  file  (FIRST_SYSTEM_UID  and
       LAST_SYSTEM_UID).  If  you want to have a specific UID, you can specify
       it using the --uid option.

       By default, system users are placed in the nogroup group.  To place the
       new  system  user  in  an  already  existing  group,  use  the --gid or
       --ingroup options.  To place the new system user in a  new  group  with
       the same ID, use the --group option.

       A home directory is created by the same rules as for normal users.  The
       new system user will have the shell /bin/false (unless overridden  with
       the  --shell option), and have logins disabled.  Skeletal configuration
       files are not copied.

   Add a user group
       If adduser is called with the --group option and without  the  --system
       option, or addgroup is called respectively, a user group will be added.


       A  GID  will  be chosen from the range specified for system GIDS in the
       configuration file (FIRST_GID, LAST_GID). To  override  that  mechanism
       you can give the GID using the --gid option.

       The group is created with no users.

   Add a system group
       If  addgroup is called with the --system option, a system group will be
       added.

       A GID will be chosen from the range specified for system  GIDS  in  the
       configuration  file  (FIRST_SYSTEM_GID,  LAST_SYSTEM_GID).  To override
       that mechanism you can give the GID using the --gid option.

       The group is created with no users.

   Add an existing user to an existing group
       If called with two non-option arguments, adduser will add  an  existing
       user to an existing group.

OPTIONS
       --conf FILE
              Use FILE instead of /etc/adduser.conf.

       --disabled-login
              Do  not  run passwd to set the password.  The user won't be able
              to use her account until the password is set.

       --disabled-password
              Like --disabled-login, but logins are still possible (for  exam‐
              ple using SSH RSA keys) but not using password authentication.

       --force-badname
              By default, user and group names are checked against the config‐
              urable regular expression NAME_REGEX  (or  NAME_REGEX_SYSTEM  if
              --system is specified) specified in the configuration file. This
              option forces adduser and addgroup to apply only  a  weak  check
              for validity of the name.

       --gecos GECOS
              Set  the  gecos field for the new entry generated.  adduser will
              not ask for finger information if this option is given.

       --gid ID
              When creating a group, this option forces the new groupid to  be
              the  given  number.   When creating a user, this option will put
              the user in that group.

       --group
              When combined with --system, a group with the same name  and  ID
              as the system user is created.  If not combined with --system, a
              group with the given name  is  created.   This  is  the  default
              action if the program is invoked as addgroup.

       --help Display brief instructions.

       --home DIR
              Use  DIR  as  the user's home directory, rather than the default
              specified by the configuration file.  If the directory does  not
              exist, it is created and skeleton files are copied.

       --shell SHELL
              Use  SHELL  as  the  user's login shell, rather than the default
              specified by the configuration file.

       --ingroup GROUP
              Add the new user to GROUP instead of a usergroup or the  default
              group  defined  by  USERS_GID  in  the configuration file.  This
              affects the users primary group.  To add additional groups,  see
              the add_extra_groups option

       --no-create-home
              Do not create the home directory, even if it doesn't exist.

       --quiet
              Suppress informational messages, only show warnings and errors.

       --debug
              Be  verbose, most useful if you want to nail down a problem with
              adduser.

}}}

///%basic
//%/

///%2
//%/
<<forEachTiddler
    script '
        window.fetItemsPerPage = 20;

        function getHeader(context,count) {
            if (!window.fetStartIndex || window.fetStartIndex < 0) 
                window.fetStartIndex = 0;

            // ensure not to page behind the last page
            if (window.fetStartIndex >= count)
                window.fetStartIndex = Math.min(Math.max(window.fetStartIndex-window.fetItemsPerPage,0),count-1);

            createTiddlyButton(context.place,"<",null,
                    function(e) {
                        window.fetStartIndex -= window.fetItemsPerPage;
                        story.refreshTiddler(context.viewerTiddler.title,null,true);
                    });
            createTiddlyButton(context.place,">",null,
                    function(e) {
                        window.fetStartIndex += window.fetItemsPerPage;
                        story.refreshTiddler(context.viewerTiddler.title,null,true);
                    });

            var startNo = window.fetStartIndex+1;
            var endNo = Math.min(count,window.fetStartIndex+window.fetItemsPerPage);

            return "("+startNo+" - "+endNo+ " of "+ count + " items)\n";
        }
    '

    write
            '(index >= window.fetStartIndex) && (index < window.fetStartIndex + 20) ? "* [["+tiddler.title+"]]\n" : ""'

        begin
            'getHeader(context,count)'
>>

// /%
With a little scripting you can use the ~ForEachTiddlerPlugin to display the result "by pages". I.e. you don't display the full result list, but (e.g.) 10 at a time. 
Using a "pagewise" display may be useful when the result may get very large. This way you avoid scrolling the window to see the result. It also speeds up things since less items need to be display at a time.

''Code''
{{{
<<forEachTiddler
    script '
        window.fetItemsPerPage = 10;

        function getHeader(context,count) {
            if (!window.fetStartIndex || window.fetStartIndex < 0) 
                window.fetStartIndex = 0;

            // ensure not to page behind the last page
            if (window.fetStartIndex >= count)
                window.fetStartIndex = Math.min(Math.max(window.fetStartIndex-window.fetItemsPerPage,0),count-1);

            createTiddlyButton(context.place,"<",null,
                    function(e) {
                        window.fetStartIndex -= window.fetItemsPerPage;
                        story.refreshTiddler(context.viewerTiddler.title,null,true);
                    });
            createTiddlyButton(context.place,">",null,
                    function(e) {
                        window.fetStartIndex += window.fetItemsPerPage;
                        story.refreshTiddler(context.viewerTiddler.title,null,true);
                    });

            var startNo = window.fetStartIndex+1;
            var endNo = Math.min(count,window.fetStartIndex+window.fetItemsPerPage);

            return "("+startNo+" - "+endNo+ " of "+ count + " items)\n";
        }
    '

    write
            '(index >= window.fetStartIndex) && (index < window.fetStartIndex + 10) ? "* [["+tiddler.title+"]]\n" : ""'

        begin
            'getHeader(context,count)'
>>
}}}
// %/
''參考文章''
1. Ubuntu下透明壓縮的檔案系統- btrfs
http://download.ithome.com.tw/article/index/id/2311?tag=rss.qu

{{item1{檔案權限}}}
{{{
-rwxr-xr-x
}}}

接著其後的 9 個字母,3 個字元為 1組,分為 3 組﹕分別是分配給 ‘user (擁有者)’ 、‘group (群組)’ 、 和 ‘others (其他使用者)’ 這三個不同使用者群的權限﹔而其中每一組使用者可以擁有這些權限﹕
{{{
‘r’  表示 readable    (可讀) 
‘w’ 表示 writable    (可寫)
‘x’  表示 executable (可執行) 
}}}

檔案是實際含有資料的地方,包括一般文字檔、資料庫內容檔、二進位可執行檔 (binary program) 等等。 因此,權限對於檔案來說,他的意義是這樣的:

* r (read):可 ''讀取'' 此一檔案的實際內容,如讀取文字檔的文字內容等;
* w (write):可以 ''修改、新增'' 該檔案的內容(''但不含刪除該檔案'');
* x (eXecute):該檔案具有可以被系統執行的權限。

那個可讀(r)代表讀取檔案內容是還好瞭解,那麼可執行 (x) 呢?這裡你就必須要小心啦! 因為在 Windows 底下一個檔案是否具有執行的能力是藉由『 副檔名 』來判斷的, 例如:.exe, .bat, .com 等等,但是在 Linux 底下,我們的檔案是否能被執行,則是藉由是否具有『x』這個權限來決定的!跟檔名是沒有絕對的關係的!

至於最後一個 w 這個權限呢?當你對一個檔案具有 w 權限時,你可以具有 ''寫入/新增/修改'' 檔案的內容的權限, 但並不具備有刪除該檔案本身的權限!對於檔案的 rwx 來說, ''主要都是針對『檔案的內容』而言'',與檔案檔名的存在與否沒有關係喔!因為檔案記錄的是實際的資料嘛!

<<toBalaNotes "file">>

{{item1{chown 改變檔案擁有者}}}
{{{
chown 指令格式 :

      chown 使用者帳號 檔案或目錄名 (該檔案 owner 或 root 使用) 

}}}

''練習 :''
{{{
# touch  install.log

# ls -al  install.log

# sudo chown bin install.log 

# ls -l 
-rw-r--r-- 1 bin users 0 Jun 25 08:53 install.log 

# sudo chown root:root install.log 

# ls -l 
-rw-r--r-- 1 root root 0 Jun 25 08:53 install.log 
}}}

''[註]'' Shell 提示字元, 如有'#' , 代表 root, Shell 提示字元, 如有'$' , 代表一般使用者

{{item1{chgrp 改變檔案所屬的群組}}}
{{{
chgrp 指令格式 : 
     chgrp  群組名稱  檔案或目錄名  (唯 root 可使用) 
}}}
''練習 :''
{{{
# chgrp users install.log 
# ls -l 
-rw-r--r-- 1 root users 68495 Jun 25 08:53 install.log

# chgrp testing install.log 
chgrp: invalid group name `testing' <== 發生錯誤訊息囉~找不到這個群組名~ 
}}}

{{item1{chmod 修改檔案權限}}}
{{{
chmod 指令格式 :
    chmod  u+rwx  檔案或目錄名 (令使用者可存讀執行本檔) 
    chmod  g+rwx  檔案或目錄名  (令同群組可存讀執行本檔) 
    chmod  o+rwx  檔案或目錄名 (令其他使用者可存讀執行本檔)
    chmod  o-rwx   檔案或目錄名  (令其他使用者不可存讀執行本檔) 
}}}

''練習 :''
{{{
# ls  -al  .bashrc 
-rw-r--r-- 1 root root 395 Jul 4 11:45 .bashrc 
# chmod 777 .bashrc 

# ls  -al  .bashrc 
-rwxrwxrwx 1 root root 395 Jul 4 11:45 .bashrc 
}}}

{{item1{實作}}}

''練習一 : 其他使用者''
1. 在第一終端機 (Alt+F1), 使用者 student 在家目錄中, 產生 look.txt 檔案

2. 檢視 look.txt 檔案詳細資訊

3. 啟動第二終端機 (Alt+F2), 使用者 obf 登入

4. 在第二終端機, 進入 student 家目錄

5. 顯示 look.txt 檔案內容 (寫出執行命令, 記錄執行結果)

6. 修改 look.txt 檔案內容 (寫出執行命令, 記錄執行結果)

7. 更改 look.txt 檔案名稱 (寫出執行命令, 記錄執行結果)

8. 刪除 look.txt 檔案 (寫出執行命令, 記錄執行結果)

9. 複製 look.txt 檔案至 /bin  

10. 複製 look.txt 檔案至 obf 的家目錄

11. 檢視 obf 家目錄的 look.txt 檔案詳細資訊

''練習二 : 加入群組''

1. 在第一終端機, 將 obf 加入 student 群組

2. 重複執行 [練習一] 的 4 ~ 8 步驟

''練習三 : 修改檔案的群組權限''

1. 在第一終端機, 將 look.txt 檔案權限改成 760

2. 重複執行 [練習一] 的 4 ~ 8 步驟

''練習四 : 改變檔案擁有人''

1. 在第一終端機, 將 look.txt 檔案擁有人改成 obf

2. 重複執行 [練習一] 的 4 ~ 8 步驟

''問題''

請問 obf 要如何才能將 look.txt 檔案刪除 ?

<<toBalaNotes "2">>

///%file
//%/

///%2
//%/
{{item1{本機登入流程圖}}}

[img[img/linux/loginprocess.gif]]

''[註]'' 上圖是描述本機登入流程, 而不是遠端登入 (ssh) 流程

{{item1{登入後程序階層圖}}}

原本 getty 是乘 6 (6*[getty]), 因本機登入成功, 所以用掉一個 終端機 (tty), 並啟動一個新的程序 : login-bash, 如下圖 : 

[img[img/linux/locallogin.png]]

{{item1{檢視終端機設定檔 (tty?.conf)}}}

''# cat /etc/init/tty2.conf''
{{{
# tty2 - getty
#
# This service maintains a getty on tty2 from the point the system is
# started until it is shut down again.

start on runlevel [23]
stop on runlevel [!23]

respawn
exec /sbin/getty -8 38400 tty2
}}}

<<toBalaNotes "1">>



///%1
//%/
''參考文章''
1. Learn Linux, 101: Hard disk layout
http://www.ibm.com/developerworks/linux/library/l-lpic1-v3-102-1/
2. Ubuntu下透明壓縮的檔案系統- btrfs
http://download.ithome.com.tw/article/index/id/2311?tag=rss.qu

{{item1{儲存裝置名稱}}}
The first SCSI drive is usually ''/dev/sda''. On an older Linux system, the first IDE hard drive is ''/dev/hda''. With the advent of serially attached (SATA) IDE drives, a mixed PATA/SATA system would sometimes use /dev/hda for the first PATA drive and /dev/sda for the first SATA drive. ''On newer systems, all IDE drives are named /dev/sda, /dev/sdb, and so on''. The change of name for IDE drives is a result of the hotplug  system, which initially supported USB drives. ''Hotplug'' allows you to plug in new devices and use them immediately, and is now used for all devices whether they are built into the system or plugged later into a running system using USB or Firewire (IEEE 1394) or potentially other types of connection.

''[註]'' 因 Hotplug 的運作, 現在所有儲存裝置 (SCSI, ATA, SATA,USB,..), 名稱均為 ''/dev/sdX''

{{item1{硬碟構造}}}
Traditionally, a hard drive is formatted into ''512 byte sectors''. All the sectors on a disk platter that can be read without moving the head constitute (構成) a ''track''. Disks usually have more than one platter (磁盤). The collection of tracks on the various platters that can be read without moving the head is called a ''cylinder''. The geometry of a hard drive is expressed in cylinders, tracks (or heads) per cylinder, and sectors/track. At the time of this writing, drive manufacturers are starting to introduce ''disks with 4K sectors''. If a filesystem still assumes 512-byte sectors, you may lose performance if a partition does not start at a sector that is on a 4K boundary.

[img[img/hdmap.png]]

''[註]'' 新一代硬碟, 每一個 Sector 是 4K

Limitations on the possible sizes for cylinders, heads, and sectors used with DOS operating systems on PC systems resulted in BIOS translating geometry (幾何) values so that larger hard drives could be supported. Eventually, even these methods were insufficient. More recent developments in disk drive technology have led to ''logical block addressing (LBA)'', so the ''CHS (cylinders, heads, sectors)'' geometry measurements are less important, and the reported geometry on a modern disk may bear little or no relation to the real physical sector layout. The larger disks in use today have forced an extension to ''LBA known as LBA48'', which reserves up to 48 bits for sector numbers.

''[註]'' 對於 Sector 的描述有 CHS 與 LBA 這二種方式, 目前電腦的 BIOS 均有提供這二種方式, 使用 LBA 是比較容易描述

{{item1{硬碟分割區}}}
''The space on a hard drive is divided (or partitioned) into partitions''. Partitions cannot overlap; space that is not allocated to a partition is called free space. The partitions have names like /dev/hda1, /dev/hda2, /dev/hda3, /dev/sda1, and so on. IDE drives are limited to 63 partitions on systems that do not use hotplug support for IDE drives. ''SCSI drives, USB drives, and IDE drives supported by hotplug are limited to 15 partitions''. A partition is often allocated as an integral number of cylinders (based on the possibly inaccurate notion of a cylinder).

If two different partitioning programs have different understandings of the nominal (名義上的) disk geometry, it is possible for one partitioning program to report an error or possible problem with partitions created by another partitioning program. You may also see this kind of problem if a disk is moved from one system to another, particularly if the BIOS capabilities are different.

You can see the nominal geometry on a Linux system using either the ''parted'' or ''fdisk'' tools. Older Linux systems also reported geometry in the /proc filesystem, in a file such as /proc/ide/hda/geometry, a file that may not be present on newer systems. 

{{item1{顯示硬碟資訊 : fdisk}}}

''顯示 fdisk 命令版本代號''
{{{
$ fdisk -v
fdisk (util-linux-ng 2.17.2)
}}}

''檢視 /dev/sdb 硬碟資訊''
{{{
$ sudo fdisk /dev/sdb

WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
         switch off the mode (command 'c') and change display units to
         sectors (command 'u').

Command (m for help): p

Disk /dev/sdb: 1073 MB, 1073741824 bytes
255 heads, 63 sectors/track, 130 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x797b64c4

所用裝置 Boot      Start         End      Blocks   Id  System
/dev/sdb1               1         130     1044193+  83  Linux

Command (m for help): q
}}}

''檢視 /dev/sda 硬碟資訊''
{{{
$ sudo fdisk /dev/sda

WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
         switch off the mode (command 'c') and change display units to
         sectors (command 'u').

Command (m for help): c                     (根據上述開頭提示訊息輸入 c)
DOS Compatibility flag is not set

Command (m for help): u                     (根據上述開頭提示訊息輸入 u)
Changing display/entry units to sectors

Command (m for help): p

Disk /dev/sda: 53.7 GB, 53687091200 bytes
255 heads, 63 sectors/track, 6527 cylinders, total 104857600 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000a410a

所用裝置 Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048   101875711    50936832   83  Linux
/dev/sda2       101877758   104855551     1488897    5  延伸的
/dev/sda5       101877760   104855551     1488896   82  Linux swap / Solaris

Command (m for help): q

}}}

''fdisk'' prints a warning about the nominal position for the end of cylinder 1024. Cylinder 1024 is important in some older systems where the BIOS is only able to boot partitions that are completely located within the first 1024 cylinders of a disk. This is most likely to occur in a BIOS that does not have LBA support, or some older boot managers. It is not usually a problem in modern machines, although you should be aware that the limit may exist.

You can use fdisk to display units in sectors, using the ''-u'' option, or you can use the ''u subcommand'' in interactive mode to toggle between sectors and cylinders. 

{{item1{顯示硬碟資訊 : parted}}}
The ''parted command'' supports several different units. 

''檢視 /dev/sdb 硬碟資訊''
{{{
$ sudo parted /dev/sdb
GNU Parted 2.2
使用 /dev/sdb
歡迎使用 GNU Parted!輸入 'help' 來檢視命令列表。
(parted) p
Model: VMware, VMware Virtual S (scsi)
磁碟/dev/sdb:1074MB
磁區大小(邏輯的/實體的):512B/512B
分割表:msdos

編號  起始點  結束點  大小    類型     檔案系統  旗標
 1    32.3kB  1069MB  1069MB  primary  fat32

(parted) u s
(parted) p
Model: VMware, VMware Virtual S (scsi)
磁碟/dev/sdb:2097152s                                      (s 代表 sector)
磁區大小(邏輯的/實體的):512B/512B
分割表:msdos

編號  起始點  結束點    大小      類型     檔案系統  旗標
 1    63s     2088449s  2088387s  primary  fat32

(parted) u chs
(parted) p
Model: VMware, VMware Virtual S (scsi)
磁碟/dev/sdb:130,138,7                                     (這三個數字, 分別代表 磁柱, 磁頭, 磁區)
磁區大小(邏輯的/實體的):512B/512B
BIOS 的磁柱、磁頭、磁區幾何結構:130,255,63。每圈磁柱是 8225kB。
分割表:msdos

編號  起始點  結束點      類型     檔案系統  旗標
 1    0,1,0   129,254,62  primary  fat32

(parted)

}}}
Note that the apparent discrepancy between the starting cylinder and ending cylinders shown by parted and fdisk output is due to the fact that parted starts counting cylinders at 0, while fdisk starts counting them at 1. Listing 3 shows that fdisk does have the same starting and ending sector as parted.

''Listing 3. Checking start and end sector numbers''
{{{
$ sudo fdisk -ul /dev/sdb

Disk /dev/sdb: 250.1 GB, 250059350016 bytes
255 heads, 63 sectors/track, 30401 cylinders, total 488397168 sectors
Units = sectors of 1 * 512 = 512 bytes
Disk identifier: 0x000404d6

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1              63      401624      200781   83  Linux
/dev/sdb2          401625   208282724   103940550   83  Linux
/dev/sdb3       208282725   488392064   140054670   83  Linux

$ echo $(( 208282725 / 255 / 63 ))
12965
}}}

{{item1{Partition types}}}
''There are three types of partition on IDE drives: primary, logical, and extended''. The ''partition table'' is located in the ''master boot record (MBR)'' of a disk. The ''MBR'' is the first sector on the disk, so the partition table is not a very large part of it. This limits the number of primary partitions on a disk to four. When more than four partitions are required, as is often the case, one of the primary partitions must instead become an extended partition.

An extended partition is simply a container for one, or usually more, logical partitions. This partitioning scheme was originally used with MS DOS and PC DOS and permits PC disks to be used by DOS, Windows, or Linux systems. A disk may contain only one extended partition. Data is stored in the logical partitions within the extended partition. You cannot store data in an extended partition without first creating a logical partition within it.

Linux numbers primary or extended partitions as 1 through 4, so dev/sda may have four primary partitions, /dev/sda1, /dev/sda2, /dev/sda3, and /dev/sda4. Or it may have a single primary partition /dev/sda1 and an extended partition /dev/sda2. If logical partitions are defined, they are numbered starting at 5, so the first logical partition on /dev/sda will be /dev/sda5, even if there are no primary partitions and one extended partition (/dev/sda1) on the disk. So if you want more than four partitions on an IDE drive, you will lose one partition number to the extended partition. Although the theoretical maximum number of partitions on an IDE drive is now limited to 15 for kernels with hotplug, you may or may not be able to create the last few. Be careful to check that everything can work if you plan on using more than 12 partitions on a drive.

The disk used in the earlier examples has three primary partitions, all formatted for Linux use. Two use the ext3 filesystem, while the other one uses ext4. ''Listing 4'' shows the output from the parted command p for an internal drive with primary, extended, and logical partitions on a Ubuntu 9.10 system and for a USB drive attached to a Fedora 12 system. Note the different filesystem types. Note also that you can specify one or more parted commands on the command line to avoid interactive mode.

''Listing 4. Displaying the partition table with parted''
{{{
$ sudo parted /dev/sda u s p
[sudo] password for ian: 
Model: ATA WDC WD6401AALS-0 (scsi)
Disk /dev/sda: 1250263728s
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number  Start       End          Size         Type      File system     Flags
 1      63s         2040254s     2040192s     primary   ext3
 2      2040255s    22523129s    20482875s    primary   linux-swap(v1)
 4      22523130s   1250258624s  1227735495s  extended                  boot
 5      22523193s   167397299s   144874107s   logical   ext3
 6      167397363s  310761359s   143363997s   logical   ext3
 7      310761423s  455442749s   144681327s   logical   ext3
 8      455442813s  600092009s   144649197s   logical   ext3

$ sudo parted /dev/sdc p
Model: WD My Book (scsi)
Disk /dev/sdc: 750GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number  Start   End    Size    Type      File system  Flags
 1      32.3kB  135GB  135GB   primary   fat32        lba
 2      135GB   750GB  616GB   extended
 5      135GB   292GB  157GB   logical   ext3
 6      292GB   479GB  187GB   logical   ext3
 7      479GB   555GB  76.5GB  logical   ext3
 8      555GB   750GB  195GB   logical   ext3
}}}

<<toBalaNotes "hdpart">>
{{item1{檢視硬碟速度}}}

''$ hdparm -t /dev/sda''
{{{
/dev/sda: Permission denied
}}}

''$ sudo hdparm -t /dev/sda''
{{{
/dev/sda:
 Timing buffered disk reads:   40 MB in  3.12 seconds =  12.80 MB/sec
}}}

在 JeOS 8.04 系統中, 並沒安裝 hdparm 命令, 請執行以下命令安裝 :
{{{
$ sudo apt-get install hdparm
}}}
<<toBalaNotes "hadrdisk">>
{{item1{為何 IDE 裝置的命名不再是 hdX?}}}
''Q1''
{{{
弟發現 suse 跟 ubuntu 會把 ATA 硬碟也顯示成 sdx,這樣一來 ATA 與 SATA 都變成了sdx,這對於同時需要兩套 linux 的我很是困擾。

主要工作在 debian,在 debian 裡能顯示 sdx 與 hdx,但是另一套練習用的 opensuse, 也把我 ATA 硬碟顯示成 sdx,結果我在 debian 下作的 lvm 跑到 suse 下大亂..., 請問有辦法讓 suse/ubuntu 這類的 linux 將 ATA 正確解讀成 hdx 嗎?還是要在 bios 做什麼設定呢?
}}}

''A1''
{{{
我記得是不知道那一版的 kernel 開始,使用新版 ata driver 的關係,才使得 ata hd 也變成 sdx 了。好像是這樣 ata, sata, scsi, esata, iscsi, 甚至是 usb stick等 removable 儲存裝置,有一個統一的架構,比較好開發維護
}}}

{{item1{為何要改變 IDE 裝置的命名規則?}}}
''Q2''
{{{
舊的 IDE 裝置命名規則為 hda、hdb、hdc、hdd,而新的裝置則依次對應為 sda、sdb、sdc、sdd。

之所以如此改變的目的何在? 有何好處?
}}}

''A2''
{{{
因為 libata 的關係。
對 PATA(IDE) 裝置沒有什麼增益。只是整合進來而已。

為什麼要把 PATA 和 SATA 整合進 libata?因為 PATA 發展的歷史很久了,kernel 裡面的 drive r越來越龐雜, 後來負責這塊的人也不打算繼續維護 PATA driver.

PATA 也就從 2.6.19 一直停止發展到現在。後來有一個人就發慈悲心,把 PATA 重寫並且和 SATA 都整合進 libata
}}}

''參考文章 ''
1. http://linux-ata.org/faq.html
2. [[Kernel Space: on the future of Linux IDE drivers|documents/html/Kernel Space - on the future of Linux IDE drivers .htm]]

<<toBalaNotes "hd">>

本文網址 : http://gis.nchc.org.tw/lsi/Linux_Basic/discuss/look.asp?id=801&ADMIN=1

[關於 137G (48 bits LBA) 以上的大硬碟支援問題]


今天買了一顆160G的硬碟,電腦卻只抓到128G。這是在網路上找到的一篇關於這個問題的資料,轉貼近來備查!

''A: [主板以及BIOS的限制]''
對 於大多數的主板,由於它們使用的都是28位元LBA硬碟定址方式,LBA方式是以邏輯塊方式使用硬碟的,每個邏輯塊的大小是512位元組。在28位元 LBA硬碟 定址方式下,邏輯塊數目的理論極限是2的28次方即268435456塊,每塊乘以512位元組,則硬碟的理論容量極限就是:268435456(塊) *512(位元組)=137,438,953,472位元組=137GB。這便是137G容量極限的由來。所以在只支援28位元ATA規範的主板裏就會出現 160G只能識別出137G的現象,針對這個情況, Maxtor率先推出48-Bit LBA Address規範, 這種規範的中心思想就是增加 CHS的位元數,把磁區位址設置為16位元的寄存器,磁頭的位址寄存器也設為16位,柱面位址寄存器不變。這樣的話,在LBA定址中可用的寄存器空間就從 28 位提高到了48位(16+16+16),這樣的話,可以定址的磁區數就為281,474,976,710,655(65,536x65, 535x65,536),整個硬碟的容量就大得驚人了281,474,976,710,655x512=144,115,188,075,855,872 位元組,也就是144155188GB(怎麼樣,這下算海量了吧,嘎嘎^_^,不過,由於現在OS的限制,理論上Windows XP最大能支持 2200GB)


''B: [作業系統對硬碟的支援情況]''
常見的作業系統,如 Windows 98、 Windows Me、 Windows 2000、Windows XP等在默認情況下,因為並不支援48位定址,所以一樣也不能支援超過137G的硬碟,根據微軟官方PDF 檔可以看出: Windows 95作業系統最高僅支援32GB的磁片管理能力(使用FAT 32格式),而 Windows 98作業系統,其可以進 行磁片完全控制的也就是64GB左右,並且Windows 98SE和Windows ME也存在這個問題,當然並不是說作業系統無法使用超過64GB容 量的硬碟,而是作業系統附帶的Fdisk無法突破64GB的容量,所以要想方便的使用和管理大容量的硬碟,還是不要考慮這幾種作業系統為好…….
可以看出,想要突破硬碟137GB的容量限制使用大硬碟,要注意以下幾點

''(1): 主板晶片組和BIOS支援大於137GB的硬碟''
就 目前看來,VIA VT8233A、VIA VT8235、VIA VT8237、SIS 961、SIS 963等,以及Intel 810~875系 列的晶片組都可以支援超過137GB容量的硬碟。至於BIOS方面,一般2002年以後發佈的BIOS都可以支援,如果你不確定,可以下一個叫 48bin LBA test program的小軟體來檢查一下(不過要在DOS下運行,最好在純DOS下而不是MS-DOS) 使用之前先掛接上一塊 容量超過137GB的大硬碟,運行該軟體,程式會自動檢測到系統中已連接ATA和ATAPI設備,並給出相應的提示資訊。如果檢測結果顯示為 “PASSED”,則說明主板BIOS支持48bit LBA;假如顯示為“FAILED”則表示不支持;如果顯示為“UNDETERMINED”則說明 測試程式也不能確定主板BIOS是否支援, 多半是因為當前系統中沒有連接超過137GB的硬碟。

如果檢測出你的主板不支持,可以用刷新BIOS的方法解決,如果你的主板很老了,廠商沒有新的BIOS發佈, 那還有兩種途徑解決:一是購買Ultra ATA/133 PCI等硬碟介面卡了,如果系統BIOS不支援通過Ultra ATA/133 PCI介面卡 引導系統,那只能把它當作從盤使用了;二硬碟廠商有發佈針對這種情況的專用工具軟體,例如希捷的DiscWizard Starter Edition、 Maxtor的MaxBlast、Western Digital的EZ Drive,可以在主板BIOS不支援的情況下驅動大容量硬碟,它們會在主板 BIOS啟動之後、作業系統啟動之前載入,三:這是絕招,實在不行換主板…卡卡卡(表撿板磚,想幹嘛?)

''(2): 使用支援大於137GB的硬碟的OS''
根據微軟官方的說法:同時滿足下列要求才可以正確使用137GB以上的硬碟:
1:必須具有48位 LBA相容BIOS
2:必須具有一個容量超過137GB的硬碟
3:必須安裝了 Windows XP 或 Windows 2000。但是,實際使用中還是遇到不少的麻煩,如果使用作業系統不恰當或者沒有正確安裝專用補丁都有可能導致資料丟失,

通過實驗,以下幾種OS可以自發支援大於137GB硬碟的全部容量
Windows XP Home+SP1
Windows XP Professional+SP1
Windows 2000 Professional+SP3(SP4)
Windows 2000 Server+SP3(SP4)

<<toBalaNotes "mainhd">>

///%hadrdisk
//%/

///%hd
//%/

///%hdpart
//%/

///%mainhd
//%/
{{item1{Command substitution}}}

''取得檔案目錄名稱''
{{{
$ mydir=$(dirname  /usr/local/share/doc/foo/foo.txt)
$ echo $mydir
/usr/local/share/doc/foo
}}}

''取出硬碟大小''

方法一
{{{
$ sudo fdisk -l /dev/sda

Disk /dev/sda: 8589 MB, 8589934592 bytes
255 heads, 63 sectors/track, 1044 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Disk identifier: 0x000cd333

所用裝置 Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1         993     7976241   83  Linux
/dev/sda2             994        1044      409657+   5  延伸的
/dev/sda5             994        1044      409626   82  Linux swap / Solaris

$ sudo fdisk -l /dev/sda | grep Disk
Disk /dev/sda: 8589 MB, 8589934592 bytes
Disk identifier: 0x000cd333
}}}

方法二
{{{
$ sudo hdsectors=$(blockdev --getsize /dev/sda)
/dev/sda: 拒絕不符權限的操作
usage: sudo -h | -K | -k | -L | -l | -V | -v
usage: sudo [-bEHPS] [-p prompt] [-u username|#uid] [VAR=value]
            {-i | -s | <command>}
usage: sudo -e [-S] [-p prompt] [-u username|#uid] file ...


$ hdsectors=$(sudo blockdev --getsize /dev/sda)
$ echo $hdsectors
16777216

$ sectorsize=$(sudo blockdev --getss /dev/sda)
$ echo $sectorsize
512

$ hdbytes=$(($hdsectors * $sectorsize))
$ echo $hdbytes
8589934592

$ hdmk=$(($hdbytes / 1048476))
$ echo $hdmk
8192

}}}

{{item1{Chopping strings like a pro}}}

{{op1{1. 向左刪除}}}
字串處理方向是由 ''左'' 向 ''右''
{{{
$ myvar=foodforthought.jpg
$ echo ${myvar##*fo}
rthought.jpg

$ echo  ${myvar#*fo}
odforthought.jpg

# 顯示 DNS IP 位址
$ mydns=$(cat /etc/resolv.conf | grep nameserver)
$ echo ${mydns##* }
192.168.56.2
}}}

{{op1{2. 向右刪除}}}
字串處理方向是由 ''右'' 向 ''左'' 
{{{
$ myfoo=“chickensoup.tar.gz”
$ echo  ${myfoo%%.*}
chickensoup


$ echo  ${myfoo%.*}
chickensoup.tar
}}}

{{op1{3. 截取字串}}}
{{{
$ ex=cowabungaxyz
$ echo  ${ex:0:3}                # 0 代表起始位址, 3 代表抓三個字
Cow

$ echo  ${ex:3:7}
abungax

## 顯示 Default Gateway
$ mygw=$(netstat -r | grep default)
$ echo $mygw
default              192.168.200.2 0.0.0.0 UG 0 0 0 eth0
$ echo ${mygw:16:15}
192.168.200.2
}}}

<<toBalaNotes "string">>

///%string
//%/
感謝你使用土芭樂知識王 - 學習筆記本, 首先請你根據以下設定程序, 設定此筆記本的版面
__{{item1{修改筆記本主標題 (SiteTitle) 及 次標題 (SiteSubTitle)}}}__
1. 展開左邊選單中的 ''[知識王管理]'' 項目
2. 點選 ''[版面管理員]'', 然後設定平台標題文字

<<toBalaSWF2 "movie/KMKTitle.swf" "820" "610" "教學影片 - 修改筆記本標題文字">>

__{{item1{產生主選單樹狀文章架構}}}__
1. 展開左邊選單中的 ''[知識王管理]'' 項目
2. 點選 ''[版面管理員]'', 然後設定資訊樹架構

<<toBalaSWF2 "movie/KMKTree.swf" "820" "610" "教學影片 - 產生主選單樹狀文章架構">>

''[注意]'' 執行完上述二項設定, 記得點選工具列中的 ''[儲存變更]'' 按鈕, 儲存你的設定並重新載入

<<toBalaNotes "setup">>


///%setup
//%/
{{op1{學習網站}}}
''1. Linux Documentation Project (此網站提供許多很棒的電子書, 包括下面二個手冊)''
http://www.tldp.org/guides.html

''2. Bash Guide for Beginners''
http://www.tldp.org/LDP/Bash-Beginners-Guide/html/index.html

''3. Advanced Bash-Scripting Guide''
http://www.tldp.org/LDP/abs/html/index.html

''4. Bash scripting for beginning system administrators''
http://www.ibm.com/developerworks/aix/library/au-getstartedbash/index.html

''5. Bash scripting Tutorial (請先閱讀此文章)''
http://linuxconfig.org/Bash_scripting_Tutorial

<<toBalaNotes "man">>


///%man
//%/
''參考文章''
1. GRUB 2 中文指南
http://wiki.ubuntu-tw.org/index.php?title=GRUB_2_%E4%B8%AD%E6%96%87%E6%8C%87%E5%8D%97
2. GNU GRUB 官方網站
http://www.gnu.org/software/grub/
3. Learn Linux, 101: Boot managers
http://www.ibm.com/developerworks/linux/library/l-lpic1-v3-102-2/index.html

{{item1{Boot Loader 的執行}}}
BIOS 讀完資訊後,接下來就是會到第一個開機裝置的 MBR 去讀取 boot loader 了,這個 boot loader 可以具有選單功能,而且還能辨識硬碟的 filesystem , 並且指向核心檔案,以將他讀入主記憶體中, MBR 是整個硬碟的第一個 sector,充其量整個大小不可能超過 512 Kbytes 的,那麼, 我們的 loader 功能這麼強,不可能只佔不到 512 Kbytes 的容量吧? 而且某些情況下,設定檔還會佔用掉不少的容量呢!怎麼辦?

為了解決這個問題,我們將 boot loader 分成兩個階段來執行 :

''第一階段 (Stage 1)'' 為 boot loader 的主程式,這個主程式必須要被安裝在開機區, 亦即是 MBR 或者是 Super block (各個分割區的 first sector)。但如前所述,因為 MBR 實在太小了, 所以通常僅安裝 boot loader 的最小主程式, 並沒有安裝 loader 的相關設定檔.

''第二階段 (Stage 2)'' 為載入 boot loader 的所有設定檔與相關的環境參數檔案。 一般來說,設定檔都在 /boot 目錄底下。

{{item1{GRUB2 簡介}}}
GRUB 2 是 Ubuntu 9.10 (Karmic Koala) 的預設開機載入和管理程式。在電腦開機時 GRUB 2 將顯示選單等待使用者輸入或是自動將控制權轉移到作業系統核心。GRUB 2 繼承自 GRUB (GRand Unified Bootloader)。它經過了完全的重寫以提供使用者可觀的靈活性和效能增進。GRUB 2 是開放原始碼軟體。

在這份指南中,GRUB 2 版本為 1.96 或更新版。傳統 GRUB (0.97 版) 將以 GRUB 稱之。

{{op1{增加功能}}}
GRUB 2 與原本的 GRUB 相比之下主要增加功能包含:
* 命令稿支援,包括條件敘述和函式
* 動態模組載入
* 救援模式
* 客製化選單
* 佈景主題
* 支援圖形化開機選單以及增進的開機影像能力
* 直接由硬碟中的可開機光碟映像檔來開機
* 新的設定檔結構
* 非 x86 平台支援(例如 PowerPC)
* 全面支援 UUID(不只在 Ubuntu)
* openSUSE 和 Fedora 尚未採用 GRUB 2 

{{op1{檢視 GRUB Loader 版本}}}
{{{
$ grub-install -v
grub-install (GNU GRUB 1.98-1ubuntu7)
}}}

{{item1{GRUB vs GRUB 2}}}
GRUB 2 的預設選單對 GRUB 使用者而言看起來很熟悉,但是在相似的表面下實則有非常巨大的相異之處。

* 在沒有安裝其他作業系統的全新 Ubuntu 9.10 安裝下,GRUB2 將會直接開機到登入提示符號或是桌面。''將不會顯示選單''。
* 沒有 /boot/grub/menu.lst。已被 /boot/grub/grub.cfg 取代。
* 在 grub 提示符號下沒有「/find boot/grub/stage1」。Stage 1.5 被淘汰了。
* 主要選單檔,/boot/grub/grub.cfg,不應再被手動編輯,即使是「root」身份。
* grub.cfg 會在任何有更新、核心被加入/移除或是使用者執行 update-grub 的時候被覆寫。
* 使用者可以編輯一個 ''客製化檔案(/etc/grub.d/40_custom)'',在其中使用者可放入自己的選項。''此檔案將不會被覆寫''。
* 主要用來改變顯示設定的設定檔是 ''/etc/default/grub''。
* 有好幾個檔案用來設定選單 - 上面提到的 /etc/default/grub,還有所有在 /etc/grub.d/ 目錄下的檔案。
* 分割區編碼變更。現在第一個分割區是 1 而不是 0。然而第一個裝置依然是 0(沒有改變)。
* 無論何時執行 update-grub 指令時,自動搜尋其他作業系統,例如 Windows。
* 在 update-grub 指令執行前,所有設定檔中變更的設定都不會生效。 

<<toBalaNotes "grub">>

{{item1{顯示核心開機資訊}}}
{{{
profx@ubuntu:~$ dmesg | tail -n 30
[   24.932622] PM: Checking swsusp image.
[   24.932915] PM: Resume from disk failed.
[   24.992225] EXT3-fs: INFO: recovery required on readonly filesystem.
[   24.992297] EXT3-fs: write access will be enabled during recovery.
[   25.047153] kjournald starting.  Commit interval 5 seconds
[   25.048262] EXT3-fs: recovery complete.
[   25.049359] EXT3-fs: mounted filesystem with ordered data mode.
[   39.350307] Linux agpgart interface v0.102
[   39.567000] agpgart: Detected an Intel 440BX Chipset.
[   39.714421] agpgart: AGP aperture is 256M @ 0x0
[   39.846027] input: Power Button (FF) as /devices/virtual/input/input1
[   39.858007] ACPI: Power Button (FF) [PWRF]
[   39.883240] input: Sleep Button (CM) as /devices/virtual/input/input2
[   39.898031] ACPI: Sleep Button (CM) [SLPB]
[   39.932767] ACPI: AC Adapter [ACAD] (on-line)
[   39.956973] piix4_smbus 0000:00:07.3: Found 0000:00:07.3 device
[   39.957746] piix4_smbus 0000:00:07.3: Host SMBus controller not enabled!
[   41.977869] eth0: link up
[   44.145458] input: PC Speaker as /devices/platform/pcspkr/input/input3
[   44.463778] input: ImPS/2 Generic Wheel Mouse as /devices/platform/i8042/serio1/input/input4
[   45.014517] parport_pc 00:08: reported by Plug and Play ACPI
[   45.019024] parport0: PC-style at 0x378, irq 7 [PCSPP,TRISTATE]
[   49.456895] NET: Registered protocol family 17
[   54.471069] loop: module loaded
[   54.574735] lp0: using parport0 (interrupt-driven).
[   55.235343] Adding 409616k swap on /dev/sda5.  Priority:-1 extents:1 across:409616k
[   55.891866] EXT3 FS on sda1, internal journal
[   56.895677] NET: Registered protocol family 10
[   56.934184] lo: Disabled Privacy Extensions
[   67.690275] eth0: no IPv6 routers present
}}}

<<toBalaNotes "grub">>

{{item1{Ubuntu 9.10 的 grub2 問題}}}
由於最新版的 Ubuntu 9.10 使用了 grub2,與原先的版本使用 grub 在設定上有些不同,如果直接從舊系統升級,可能在安裝完畢後無法開機。

狀況是開機時會停在「Grub Error 15」的地方。

如果上網搜尋,會找到許多關於舊版的解決方案,比如修改 /boot/grub/menu.lst 這個檔案,但在 grub2 裡面已經沒有這個檔案了,當然也就無從改起。

我自己測試有效的方法如下:

1. 拿出 ubuntu 9.10 的 LiveCD,並用它開機。
2. 打開終端機 (Terminal) 程式。並依照以下指定輸入。
3. sudo fdisk -l (看看自己有哪些硬碟,並分別使用哪些代號,例如如果你的系統是裝在 /dev/sda1 中,請記下來,以下用這個代號作為例子。)
4. sudo mount /dev/sda1 /mnt (將自己安裝的系統掛載到 /mnt,如果系統的 /boot 在另一個硬碟,請一併掛到 /mnt 下。)
5. sudo mount –bind /dev /mnt/dev
6. sudo chroot /mnt (chroot 到 /mnt 中,這時候你會變成 root 身份,因此以下指令不需要再用 sudo。)
7. nano /etc/default/grub (看看這個檔案有什麼需要修改的,如果習慣別的編輯器,例如 vi,則將 nano 換成 vi 即可。)
8. update-grub (這是最重要的更新指令啦!)
9. grub-install /dev/sda (將 grub 的資料寫入硬碟 MBR 區)
10. grub-install –recheck /dev/sda (如果上面的步驟有發生錯誤,可以用這個指令在檢查一遍。)
11. (按 Ctrl-D 離開 chroot 環境,回到原來的 shell。)
12. sudo umount /mnt/dev (將剛剛掛上的資料夾卸載)
13. sudo umount /mnt

grub2 有了相當多的改進,對使用者最直接的感受,就是可以用自己設定的圖形介面進行多重開機。

///%grub
//%/
''參考網站''
1. [[The LPIC Program (官方網站)|http://www.lpi.org/eng/certification/the_lpic_program]]
2. [[The Ultimate Site for Certified IT Professionals|http://certcities.com/certs/linux_unix/]]
3. [[IBM LPIC-I exam-prep tutorials (適用 2000 一月初版考試)|documents/html/LPIC-I exam-prep tutorials.html]]
4. [[IBM A roadmap for LPIC-1 (適用 2009 四月新版考試)|http://www.ibm.com/developerworks/linux/library/l-lpic1-v3-map/index.html?S_TACT=105AGX03&S_CMP=ZHP]]
5. [[國際認證-考試信息|http://blog.itcert.org/]]

{{item1{LPI (Linux Professtional Institute)   認證介紹}}}
LPI 認證是由 Linux 國際專業協會(Linux Professional Institute 簡稱‘LPI’)的國際性的 Linux 認證機構,LPI 致力推廣和發展開放源碼軟件,將 Linux 專業技術和開放源碼推廣至全世界。它提供專業Linux人員認證的一個管道,並讓企業聘僱 Linux 專業認證人才的一項標準。它的計劃是建立出一個專業的、通用的 Linux 認證測驗專案。目前支援 LPI 的計劃成員有:Caldera Systems、SuSe、TurboLinux、IBM、SGI、Linuxcare等公司。

Linux 使用人口正急速增加中,到公元 2004 年光是在美國,這塊市場就成長到3億1千1百萬美金。因此,可想而知當前 Linux 作為企業資訊解決方案的重要性及緊要性與日俱增,相關的工作機會將會越來越多,而技術能力的要求也更被企業界所期待,所以不管在哪個行業,Linux 工作者都必須不斷的藉由自我學習、接受訓練課程或是參加各式的專業認證來充實自己,使自己在工作上可以更加得心應手。

__{{op1{LPI Level 1 (General Linux)}}}__

|試卷編號|題數|時間|費用|
|117-101|65|90|100.00 USD|
|117-102|58|90|100.00 USD|

''117-101 測試範圍 (Weight 總數是 60)''
網址 : http://www.lpi.org/eng/certification/the_lpic_program/lpic_1/exam_101_detailed_objectives
{{{
Topic 101: System Architecture
  1. Determine and configure hardware settings (Weight 2)
  2. Boot the system (Weight 3)
  3. Change runlevels and shutdown or reboot system (Weight 3)

Topic 102: Linux Installation and Package Management
  1. Design hard disk layout  (Weight 2) 
  2. Install a boot manager (Weight 2)
  3. Manage shared libraries (Weight 1)
  4. Use Debian package management (Weight 3)
  5. Use RPM and YUM package management (Weight 3)   

Topic 103: GNU and Unix Commands
  1. Work on the command line (Weight 4)
  2. Process text streams using filters (Weight 3)
  3. Perform basic file management (Weight 4)
  4. Use streams, pipes and redirects (Weight 4)  
  5. Create, monitor and kill processes (Weight 4)
  6. Modify process execution priorities (Weight 2)
  7. Search text files using regular expressions (Weight 2)
  8. Perform basic file editing operations using vi (Weight 3)

Topic 104: Devices, Linux Filesystems, Filesystem Hierarchy Standard
  1. Create partitions and filesystems (Weight 2)
  2. Maintain the integrity of filesystems (Weight 2)
  3. Control mounting and unmounting of filesystems (Weight 3)
  4. Manage disk quotas (Weight 1)
  5. Manage file permissions and ownership (Weight 3)
  6. Create and change hard and symbolic links (Weight 2)
  7. Find system files and place files in the correct location (Weight 2)           
}}}

''117-102 測試範圍 (Weight 總數是 60)''
網址 : http://www.lpi.org/eng/certification/the_lpic_program/lpic_1/exam_102_detailed_objectives
{{{
Topic 105: Shells, Scripting and Data Management
  1. Customize and use the shell environment (Weight 4)
  2. Customize or write simple scripts (Weight 4)
  3. SQL data management (Weight 2)

Topic 106: User Interfaces and Desktops
  1. Install and configure X11 (Weight 2)
  2. Setup a display manager (Weight 2)
  3. Accessibility (Weight 1)

Topic 107: Administrative Tasks
  1. Manage user and group accounts and related system files (Weight 5)
  2. Automate system administration tasks by scheduling jobs (Weight 4)
  3. Localisation and internationalisation (Weight 3)

Topic 108: Essential System Services
  1. Maintain system time (Weight 3)
  2. System logging (Weight 2)
  3. Mail Tranfer Agent (MTA) basics (Weight 3)
  4. Manage printers and printing (Weight 2)     
     
Topic 109: Networking Fundamentals
  1. Fundamentals of internet protocols (Weight 4)
  2. Basic network configuration (Weight 4)
  3. Basic network troubleshooting (Weight 4)
  4. Configure client side DNS (Weight 2)
    
Topic 110: Security
  1. Perform security administration tasks (Weight 3)
  2. Setup host security (Weight 3)
  3. Securing data with encryption (Weight 3)   
}}}

__{{op1{LPI Level 2 (Intermediate Linux)}}}__
試卷編號:117-201、117-202
測試範圍:
{{{
‧能管理中小型的網絡
‧設計、執行、維護、保持系統一致,安全和障礙修理中小型的混合(MS,Linux)網絡包括:
‧局部區域網路伺服器
‧網上通道(firewall,proxy,mail,news)
‧網上伺服器(web server,FTP server)
‧監督助理工作
‧建議自動化和購物管理
}}}

__{{op1{LPI Level 3 (Intermediate Linux)}}}__
試卷編號:117-301、117-302
測試範圍:
{{{
‧設計及建置 Linux 解決方案,適用於大型企業或多台伺服器,負載較大的網站
‧在有預算限制的情況下規劃一個專案
‧提供進階系統管理的諮詢服務
}}}

{{op1{How much do LPI exams cost?}}}
Our intention has always been to provide testing at the lowest possible cost. As of ''January 1, 2009'' our exams will cost ''$160 US'' in most locales with the exception of our LPI-301 exam which is usually priced at $260 US. Prices may vary in some jurisdictions due to currency conversions and exchange rates.

{{op1{How are the test scores computed? How many questions do I need to answer correctly to pass? What is the maximum score? How good is my score of ...?}}}
As of April 1, 2009, all exam weights for LPI exams have been standardized to ''60 weights''. The 301 exam is a current exception with ''50 weights''.

Regardless of weight totals each exam score is ''between 200 and 800''. ''A passing score is 500''. However, the number of correct questions required to achieve a score of 500 varies with the overall difficulty of the specific exam that is taken.

The number of questions on the exam is also tied to the total of the weights of the objectives on the exam. ''With a total weight count of 60, the exam will have 60 questions''. For each weighting, there will be one question. For example, if an objective has a weight of 4, there will be 4 questions on the exam related to the objective.

{{item1{通過 LPIC 認證者可申請 Novell CLA 證書}}}
已通過 LPIC 認證的學員,毋需額外的費用及考試,直接可向 Novel 申請 Novell Certified Linux Administrator 證書。

我尋著信件所指示的網址,然後逐步完成各項步驟後,已經成功取得 Novell CLA 證書。

只要你曾經通過 LPIC 認證的學員,應該都會收到這份通知函。因故沒有收到通知的學員,看到這篇,也可以憑著 LPI ID(在官方寄的小卡片上)及當時註冊的密碼,取得這份證書。

雖然說多這一張,不見得會有什麼幫助,但畢竟這是 LPIC 學員的權利,而且應該沒有人會嫌證書太多吧!

申請 NCLA 網址
http://practicum.novell.com/LPI2CLAForm.php

查詢 LPIC 的認證碼
https://cs.lpi.org/caf/Xamman/candidate_area

{{item1{LPIC-1 新版中文紙本考試 2009/5月推出}}}
LPI 於今年4月推出新版考試內容後,也針對臺灣考生第 3 度推出紙本測驗,IT 人可以選擇正體中文或英文的考試題目應考。從5月開始,將在全臺灣 5 個考場舉辦 6 場 LPIC-1 的 ''紙本測驗''。

由 Linux 推廣基金會 LPI 推出的唯一廠商中立型的 Linux 認證 LPIC(Linux Professional Institute Certified)將於2009年4月推出LPIC-1新版認證考試,臺灣也將於5月推出新版正體中文紙本考試。

臺灣 LPI 表示,除了重新調整正體中文考試的語意外,也針對臺灣考生提供考試前3周報名者,享有每科報名費用減免10美元的優惠,報名費用只要 145 美元。

2008年10月中,LPI 針對第一級基礎認證 LPIC-1 和第二級進階認證 LPIC-2 推出新版的課程內容。

LPI 大中華區臺灣分部總經理薛煒立表示,新版考試主要著重在認證工程師的可用性與實戰能力,以往靠背考古題通過考試的方式將不適用。他舉例而言,新版LPIC考試便刪除了一些如 PCMCIA、ISA 等硬體組態的考題,在題目設計上,則偏向實務應用,例如安裝情境模擬,像是系統安裝時可能會出現的錯誤等。

在新版考試正式上線的同時,薛煒立表示,為了讓更多 IT 人能突破國際認證一律採用英文考試的門檻,測出 IT 人的IT實力,而不是英文能力,LPI 臺灣也第 3 度推出正體中文和英文的紙本考試。「此次LPI 也重新調整中文紙本考試的語意,以期更符合臺灣IT人平常的使用習慣。」他說。

臺灣 LPI 顧問講師楊振和表示,在臺灣 LPI 推出的紙本考試,IT 人可以選擇正體中文的考試或者是英文考試,這兩種測驗模式的內容和範圍都是相同的,差別只在於 IT 人考試時,所使用的語言不同而已。

{{item1{LPI 發佈新的 recertification 規定:未來 LPIC 證照將不再終生有效}}}
LPIC 證照要「重考」了,新的重新認證規章己經正式發佈了;由取得認證日起算,在二年後就要準備重新認證的程序。

LPI 會在取得認證二年後建議做重新認證(recertification)的動作,若要讓取得的 LPIC 認證有效(ACTIVE),就必須在五年內完成重新認證的工作。重新認證必須通過持有最高認證等級的所有最新考試,通過重新認證後,證書的狀態便會更新為 ACTIVE,有效期間為五年。

當取得較高等級的認證後,由取得較高等級之日起算,所有較低等級的認證狀態都會變更為 ACTIVE,期限一樣是五年。若沒有重新進行認證考試,並且讓認證失效的話,那麼就要重新取得所有認證,包含目前的最高等級與較低等級的認證。

LPI 由 2004 年 9 月 1 日開始,啟用了認證狀態資料庫,透過此資料庫能查詢證照的狀態(ACTIVE 或 INACTIVE),以往在此日期以前所取得的認證都被視為終生有效,不過在新的規章裡,LPI 將不再賦與該早期認證的終生有效權利。在 2004 年 9 月 1 日前取得認證的朋友,仍然要根據最新訂定的規章乖乖進行認證的工作。

因此,LPIC 認證將不再終生有效,原先的「終生版本」將由取得認證之日算起五年內有效。所以如果你的 LPIC 證照是在 2004 年 9 月 1 日之後取得的話,照這樣算來,就要在 2009 年 9 月 1 日前重新認證完畢;那如果是更早期取得的認證不就完蛋了嗎,很可能再過幾天就到期了啊!

不過,在 LPI 於 2006 年 12 月 1 日(美國時間)發表的新規章裡提到,在 2003 年 9 月 1 日之前取得的認證,只要在 2008 年 9 月 1 日前重新認證即可,這段期間內,證照仍視為有效(ACTIVE)。
<<toBalaNotes "lpic">>
///%lpic
//%/
''參考文章''
1. 企業網路常見架構
http://www.tts.bz/archives/165

{{item1{回顧 TCP/IP}}}

[img[img/tcpiproadmap.png]]

{{item1{TCP/IP Stack}}}

[img[img/tcp_ip_layers.gif]]
<<toBalaNotes "1">>
{{item1{TCP/IP 實體網路}}}

[img[img/linux/tcpnet.png]]

{{op1{1. Collision Domain}}}
Nodes in a shared environment can collide with each other when attempting to transmit at the same time.

''HUB'' 是 ''Collision Domain'' 連接裝置, Bridge 或 Switch 是區隔裝置
Cisco 1538 series Micro Hubs 10/100

[img[img/hubstack.jpg]]

{{op1{2. Broadcast Domain}}}
The area of a network that a broadcast frame can reach is  known as a broadcast domain

''Layer 2 Bridge'' 或 ''Switch'' 是 Broadcast Domain 的連接裝置, 而 Layer 3 Switch 或 Router 是區隔裝置. 

[img[img/switchstack.jpg]]
D-Link : DES3226S - 24-Port 10/100Mbps Fast Ethernet Stackable Managed Switch with Optional Gigabit

{{item1{Private Addressing}}}
以下 IP 封包是無法透通 網際網路 (Internet), 如要連接到網際網路, 必須透過 Internet Gateway,Proxy, Firewall 等網路設備

''Class A''
10.0.0.0 ~ 10.255.255.255/8

''Class B''
172.16.0.0 ~ 172.31.255.255/16

''Class C''
192.168.0.0 ~ 192.168.0.255/24
192.168.1.0 ~ 192.168.1.255/24
192.168.2.0 ~ 192.168.2.255/24
                                       :
''APIPA''
169.254.0.0/16

<<toBalaNotes "2">>
{{item1{Class Inter-Domain Routing}}}
A subnet mask is a bitmask which shows where the network address ends and the host address begins. ''CIDR'' uses variable length subnet masks (VLSM) to allocate IP addresses to subnets according to individual need, rather than some general network-wide rule. Thus the network/host division can occur at any bit boundary in the address. The process can be recursive, with a portion of the address space being further divided into even smaller portions, through the use of masks which cover more bits.

Because the normal class distinctions are ignored, the new system was called classless routing. This led to the original system being called, by back-formation, classful routing.* 

''[註]''  RIP  V1 不支援 VLSM 及 CIDR

<<toBalaNotes "3">>


///%1
//%/

///%2
//%/

///%3
//%/
{{item1{main}}}
main 即「基本」組件,其中只包含符合 Ubuntu 的許可證要求並可以從 Ubuntu 團隊中獲得支援的軟體,致力於滿足日常使用,位於這個組件中的軟體可以確保得到技術支援和及時的安全更新。此組件內的軟體是必須符合 Ubuntu 版權要求(Ubuntu license requirements)的自由軟體,而 Ubuntu 版權要求大致上與 Debian 自由軟體指導綱要(Debian Free Software Guidelines)相同。

{{item1{restricted}}}
restricted 即「受限」組件,其中包含了非常重要的,但並不具有合適的自由許可證的軟體,例如只能以二進位形式獲得的顯示卡驅動程式。由於 Ubuntu 開發者無法獲得相應的原始碼,restricted 組件能夠獲得的支援與 main 組件相比是非常有限的。

{{item1{universe}}}
universe 即「社群維護」組件,其中包含的軟體種類繁多,它們可能採用受限於許可證,可能不是,但都不為 Ubuntu 團隊所支援。

{{item1{multiverse}}}
multiverse 即「非自由」組件,其中包括了不符合自由軟體要求而且不被 Ubuntu 團隊支援的軟體套件,通常為商業公司編寫的軟體。

{{item1{搜尋套件}}}

搜尋網站 : http://packages.ubuntu.com/

''[backport 的定義]'' 
<software> To make a feature from a later version of a piece of software available in an earlier version.  Backporting of features enables users of the older version to benefit from a feature without upgrading fully.

<<toBalaNotes "package">>


///%package
//%/
{{item1{修改單一 DNS IP 位址}}}

''1. 取出 DNS IP 位址''
{{{
$ cat /etc/resolv.conf
nameserver 168.95.1.1
domain localdomain
search localdomain

$ grep nameserver /etc/resolv.conf
nameserver 168.95.1.1

$ d=$(grep nameserver /etc/resolv.conf)
$ echo ${d##* }
168.95.1.1
}}}

''2. 撰寫修改 DNS IP 位址程式''
{{{
$ nano chgdns.sh
#!/bin/bash

[ "$USER" != "root" ] && echo "need root" && exit 1

d=$(grep nameserver /etc/resolv.conf)
dns=${d##* }

if [ -n "$dns" ]; then
   echo "DNS Client IP : $dns"
   read -p "change DNS Client IP (y/n) " ans
   if [ "$ans" == "y" ]; then
      read -p "New DNS Client IP : " ndns
      cat /etc/resolv.conf | sed "s/$dns/$ndns/" &> /tmp/chgdns.tmp
      [ "$?" == 0 ] && cp /tmp/chgdns.tmp /etc/resolv.conf && echo "ok"
   fi
fi

exit 0
}}}

{{item1{修改多個 DNS IP 位址}}}

''1. 取出多個 DNS IP 位址''
{{{
$ cat /etc/resolv.conf
nameserver 140.137.202.20
nameserver 140.137.198.21
nameserver

$ cat /etc/resolv.conf | grep nameserver
nameserver 140.137.202.20
nameserver 140.137.198.21
nameserver

$ cat /etc/resolv.conf | grep nameserver | fmt -u
nameserver 140.137.202.20 nameserver 140.137.198.21 nameserver

$ n=$(cat /etc/resolv.conf | grep nameserver | fmt -u)
$ echo $n
nameserver 140.137.202.20 nameserver 140.137.198.21 nameserver

$ echo $n | sed 's/nameserver//g'
 140.137.202.20  140.137.198.21 
}}}

''2. 撰寫修改多個 DNS IP 位址程式''
{{{
#!/bin/bash

[ "$USER" != "root" ] && echo "need root" && exit 1
n=$(cat /etc/resolv.conf | grep nameserver | fmt -u | sed 's/nameserver//g')

for  d  in $n
do
   echo "Nameserver : $d"
   read -p "change DNS (y/n) " ans
   if [ "$ans" == "y" ]; then
      read -p "New DNS Address : " nd
      cat /etc/resolv.conf | sed "s/$d/$nd/" >/tmp/dns.chg
      cp /tmp/dns.chg /etc/resolv.conf
   fi
done
}}}


<<toBalaNotes "1">>



///%1
//%/
''參考文章''
1. Learn Linux, 101: Boot the system (必讀)
http://www.ibm.com/developerworks/linux/library/l-lpic1-v3-101-2/
2. Parallelize applications for faster Linux booting
http://www.ibm.com/developerworks/library/l-boot-faster/
3. The Linux Login Process (必讀)
http://www.comptechdoc.org/os/linux/howlinuxworks/linux_hllogin.html
4. Autologin with getty on linux console
http://neelesh-gurjar.livejournal.com/10872.html

{{item1{Linux 系統開機三階段}}}

[img[img/linux/linuxboot.gif]]

@@color:blue;{{op1{BIOS (第一階段)}}}@@

When you first turn on a computer or reset it, the computer's processor begins execution at a well-known location in what's called the ''basic input/output system (BIOS)''. BIOS is typically stored in a flash memory device on the system's motherboard. The BIOS has many jobs, such as initial testing of basic components (such as the system's memory) and determining how to boot the operating system. As PC-based computers are extremely flexible, the ''boot device'' can be one of many individual devices attached to the motherboard, including ''hard disks'', ''CD-ROMs'', or other devices such as the ''network interface''.

You can optimize the process of determining the boot device by selecting the device from which you'll most commonly boot (typically, the hard disk). But by far, the most time-consuming aspect of the BIOS stage is in memory test. Disabling certain aspects of this test (such as a full memory test) can certainly help boot speed but at the cost of a boot-time system integrity test.

@@color:blue;{{op1{Kernel boot (第二階段)}}}@@

When a boot device is found, the Linux kernel boot process begins. This process occurs in (approximately) two stages -- ''first-stage boot'' and ''second-stage boot''. The ''first stage'' consists of a simple boot loader (found on the boot device's master boot record, or MBR), whose job is to load the second-stage boot loader. 'The ''first-stage boot loader'' finds the second-stage boot loader using the ''partition table''. The first-stage boot loader scans the table, looking for the active partition; when the loader locates the partition, it loads the second-stage boot loader into RAM and invokes it.

With the ''second-stage boot loader'' in RAM, the ''Linux kernel image'' and the ''initial RAM disk image (initrd)'' are loaded into RAM. When the kernel is invoked, it decompresses itself into high memory and copies the initrd for later mounting and use.

The kernel boot process is fairly complicated but very fast, as most of the code is written in the system's machine language. At the end of the kernel boot sequence, the init process starts. As ''init is the first process'' created in a Linux system, ''it's the mother of all other processes (all processes are descendants of init)''.

''[註]'' LILO and GRUB
The first-stage and second-stage boot loaders are better known as LInux LOader (LILO) or GRand Unified Bootloader (GRUB), depending on which name your system uses.

@@color:blue;{{op1{System init (第三階段)}}}@@

''The init process -- is the first process created as the kernel boot sequence is completed''. Linux uses the init process to initialize the services and applications that make Linux useful.

When the init process starts, it opens a file called ''/etc/inittab (Ubuntu 9.10 以後就沒使用)''. This file is the configuration file for init and defines how to initialize the system. This file also contains information about what to do when a power failure occurs (if the system supports it) and how to react when it detects the Ctrl-Alt-Delete key sequence. Look at the short segment of this file shown in Listing 1 to understand what it provides.

The inittab configuration file defines several entries with a common format: id:runlevels:action:process. The id is a sequence of characters that uniquely identifies the entry. The runlevels define the runlevels for which the action should be taken. The action specifies the particular action to take. Finally, process defines the process to be executed.

<<toBalaNotes "1">>

{{item1{詳述開機流程}}}
Before we get into LILO and GRUB, let's review how a PC starts or boots. Code called BIOS (for Basic Input Output Service) is stored in non-volatile memory such as a ROM, EEPROM, or flash memory. When the PC is turned on or rebooted, this code is executed. Usually it performs a power-on self test (POST) to check the machine. Finally, it loads the first sector from the ''master boot record (MBR)'' on the boot drive.

As discussed in the article "[[Learn Linux 101: Hard disk layout,|http://www.ibm.com/developerworks/linux/library/l-lpic1-v3-102-1/]]" the MBR also contains the ''partition table (分割表)'', so the amount of executable code in the MBR is less than 512 bytes, which is not very much code. Note that every disk, even a floppy, contains executable code in its MBR, even if the code is only enough to put out a message such as "Non-bootable disk in drive A:". This code that is loaded by BIOS from this first sector is called the ''first stage boot loader'' or the ''stage 1 boot loader''.

The standard hard drive MBR used by MS DOS, PC DOS, and Windows® operating systems checks the partition table to find a primary partition on the boot drive that is marked as active, loads the first sector from that partition, and passes control to the beginning of the loaded code. This new piece of code is also known as the ''partition boot record''. The partition boot record is actually another stage 1 boot loader, but this one has just enough intelligence to load a set of blocks from the partition. The code in this new set of blocks is called the ''stage 2 boot loader''. As used by MS-DOS and PC-DOS, the stage 2 loader proceeds directly to load the rest of operating system. This is how your operating system pulls itself up by its bootstraps until it is up and running.

''[註]'' MBR 根據分割表中, 載入標示 Active 分割區所指的第一個 Sector, 然後執行此 Sector 中的程式 (partition boot record), partition boot record 主要功能是在同一個分割區中, 啟動 stage 2 boot loader, 而作業系統就是由 stage 2 boot loader 啟動

This works fine for a system with a single operating system. What happens if you want multiple operating systems, say OS/2, Windows XP, and three different Linux distributions? You could use some program (such as the DOS FDISK program) to change the active partition and reboot. This is cumbersome. Furthermore, a disk can have only four primary partitions, and the standard MBR can have only one active primary partition; it cannot boot from a logical partition. But our hypothetical (假想) example cited five operating systems, each of which needs a partition. Oops!

The solution lies in using some special code that allows a user to choose which operating system to boot. Examples include:

''1. Loadlin''
A DOS executable program that is invoked from a running DOS system to boot a Linux partition. This was popular when setting up a multi-boot system was a complex and risky process. 

''[註]'' 執行標準啟動程序, 啟動 DOS, 然後在 DOS 系統中, 執行 Loadin 執行檔去啟動 Linux 系統

''2. OS/2 Boot Manager''
A program that is installed in a small dedicated partition. The partition is marked active, and the standard MBR boot process starts the OS/2 Boot Manager, which presents a menu allowing you to choose which operating system to boot.

''[註]'' OS/2 Boot Manager 儲存在標示 Active 分割區中, 由標準的 MBR 啟動程序, 來啟動 OS/2 Boot Manager

''3. A smart boot loader''
A program that can reside on an operating system partition and is invoked either by the partition boot record of an active partition or by the master boot record. Examples include:
{{{
* BootMagic, part of Norton PartitionMagic
* LILO, the LInux LOader
* GRUB, the GRand Unified Boot loader (now referred to as GRUB Legacy)
* GRUB 2, a new boot loader that is just starting to appear in common distributions
}}}

''[註]'' 上述 Smart Boot Loader 可由 partition boot record 或 MBR 來啟動

Evidently, if you can pass control of the system to some program that has more than 512 bytes of code to accomplish its task, then it isn't too hard to allow booting from logical partitions, or booting from partitions that are not on the boot drive. All of these solutions allow these possibilities, either because they can load a boot record from an arbitrary partition, or because they have some understanding of what file or files to load to start the boot process.

{{op1{Chain loading}}}
When a boot manager gets control, one thing that it could possibly load is another boot manager. This is called chain loading, and it most frequently occurs when the boot manager that is located in the master boot record (MBR) loads the boot loader that is in a partition boot record. This is almost always done when a Linux boot loader is asked to boot a Windows or DOS partition, but can also be done when the Linux boot loader for one system is asked to load the boot loader for another system. For example, you might use LILO in one partition to launch the LILO in another partition's boot record in order to start the Linux system in that partition.

{{op1{Linux boot loaders}}}
From here on, we will focus on LILO and GRUB as these are the boot loaders included with most Linux distributions. LILO has been around for a while. GRUB is newer. The original GRUB has now become ''GRUB Legacy'', and GRUB 2 is being developed under the auspices (贊助) of the Free Software Foundation (see Resources for details). We will discuss GRUB 2 briefly, mostly so you have some idea of the major differences and how GRUB and GRUB 2 can coexist. For the rest of this article, we assume GRUB means GRUB Legacy, unless the context specifically implies GRUB 2. ''A new version of LILO called ELILO'' (which is designed for booting systems that use Intel's Extensible Firmware Interface, or EFI, rather than BIOS) is also available. See Resources for additional information about GRUB 2 and ELILO.

The installation process for your distribution will probably give you a choice of which boot loader to set up. Either GRUB or LILO will work with most modern disks, although some distributions, notably Fedora, no longer ship LILO. Remember that disk technology has advanced rapidly, so you should always make sure that your chosen boot loader, as well as your chosen Linux distribution (or other operating system), as well as your system BIOS, will work with your shiny new disk. Failure to do so may result in loss of data. Likewise, if you're adding a new distribution to an existing system, you may need to make sure you have the latest LILO or GRUB in your MBR. You will also need a fairly recent version of either GRUB or LILO if you plan to boot from an LVM or RAID disk.

The ''stage 2 loaders'' used in LILO and GRUB allow you to choose from several operating systems or versions to load. However, LILO and GRUB differ significantly in that a change to the system requires you to use a command to recreate the LILO boot setup whenever you upgrade a kernel or make certain other changes to your system, while GRUB can accomplish this through a configuration text file that you can edit. GRUB 2 also requires a rebuild from a configuration file that is normally stored in /etc.

<<toBalaNotes "start">>

{{item1{GRUB 2 修改 MBR}}}
Ubuntu Server 10.04 安裝 GRUB 2 時, 會詢問是否修改 MBR, 請看下圖 : 

[img[img/ubuntu10.4/Server/server_install19.PNG]]

///%start
//%/

///%1
//%/
''參考文章''
1. Learn Linux, 101: Create, monitor, and kill processes 
http://www.ibm.com/developerworks/linux/library/l-lpic1-v3-103-5/index.html

{{item1{顯示程序資訊}}}
To see every process on the system using BSD syntax:

''$ ps aux''
{{{
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  1.2  0.2   1904   776 ?        Ss   23:09   0:07 /sbin/init
root         2  0.0  0.0      0     0 ?        S<   23:09   0:00 [kthreadd]
root         3  0.0  0.0      0     0 ?        S<   23:09   0:00 [migration/0]
root         4  0.0  0.0      0     0 ?        S<   23:09   0:00 [ksoftirqd/0]
root         5  0.0  0.0      0     0 ?        S<   23:09   0:00 [watchdog/0]
                                                       :
syslog    2265  0.0  0.1   2040   708 ?        Ss   23:09   0:00 /sbin/syslogd -u syslog
root      2283  0.6  0.1   1968   536 ?        S    23:09   0:03 /bin/dd bs 1 if /proc/kms
klog      2285  0.2  0.6   3480  2308 ?        Ss   23:09   0:01 /sbin/klogd -P /var/run/k
bind      2305  0.0  2.2  41536  8488 ?        Ssl  23:09   0:00 /usr/sbin/named -u bind
root      2326  0.0  0.2   5436  1108 ?        Ss   23:09   0:00 /usr/sbin/sshd
root      2420  0.0  0.0      0     0 ?        S<   23:10   0:00 [vmmemctl]
root      2527  0.3  0.3   3324  1332 ?        Ss   23:10   0:01 /usr/lib/vmware-tools/sbi
daemon    2582  0.0  0.1   2096   452 ?        Ss   23:10   0:00 /usr/sbin/atd
root      2607  0.0  0.2   3480  1032 ?        Ss   23:10   0:00 /usr/sbin/cron
root      2626  0.0  0.1   1808   532 tty1     Ss+  23:10   0:00 /sbin/getty 38400 tty1
root      2664  1.7  0.7   8232  2700 ?        Ss   23:19   0:00 sshd: tobala [priv]
tobala    2666  1.0  0.4   8232  1624 ?        S    23:19   0:00 sshd: tobala@pts/0
tobala    2667  4.4  0.7   5704  2960 pts/0    Ss   23:19   0:00 -bash
tobala    2688  0.0  0.2   2768  1036 pts/0    R+   23:19   0:00 ps aux
}}}

''ps 命令參數說明''
{{{
-l:長格式顯示
-u:顯示使用者名稱和起始時間
-i:顯示各程式的詳細執行情況
-s:顯示各程式的訊號名稱
-v:顯示虛擬記憶體使用情況
-m:顯示記憶體分配情形
-f:顯示執行的路行群
-a:其它使用者執行的程式一併顯示出來
-x:顯示所有程序
-r:顯示前景執行的程式
-c:只顯示執行程式的名字
-e:顯示執行程式的環境變數
-f:不顯示標題欄
-w:若訊息一列無法容納,則換列顯示 
}}}

{{item1{以執行命令名稱查詢}}}

''$ ps u -C sshd''
{{{
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root      2326  0.0  0.2   5436  1108 ?        Ss   23:09   0:00 /usr/sbin/sshd
root      2664  0.1  0.7   8232  2700 ?        Ss   23:19   0:00 sshd: tobala [priv]
tobala    2666  0.1  0.4   8232  1624 ?        S    23:19   0:00 sshd: tobala@pts/0
}}}

''$ ps u -C named''
{{{
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
bind      2305  0.0  2.2  41536  8488 ?        Ssl  23:09   0:00 /usr/sbin/named -u bind
}}}

{{item1{階層式顯示所有程序關連}}}

''$ pstree -ph | cat -n''
{{{
     1  init(1)-+-acpid(2231)
     2          |-atd(2582)
     3          |-cron(2607)
     4          |-dd(2283)
     5          |-getty(2161)
     6          |-getty(2162)
     7          |-getty(2170)
     8          |-getty(2174)
     9          |-getty(2177)
    10          |-getty(2626)
    11          |-klogd(2285)
    12          |-named(2305)-+-{named}(2306)
    13          |             |-{named}(2307)
    14          |             `-{named}(2308)
    15          |-sshd(2326)---sshd(2664)---sshd(2666)---bash(2667)-+-cat(2754)
    16          |                                                   `-pstree(2753)
    17          |-syslogd(2265)
    18          |-udevd(876)
    19          `-vmware-guestd(2527)
}}}

''[註]'' 在 JeOS 8.04 中需安裝 psmisc 套件, 才有 pstree 命令

{{item1{動態顯示程序資訊}}}

''每一秒更新一次資訊''
{{{
$ top -d 1
top - 23:33:53 up 24 min,  1 user,  load average: 0.01, 0.02, 0.02
Tasks:  60 total,   1 running,  59 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0%us,  1.9%sy,  0.0%ni, 98.1%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:    379900k total,    60636k used,   319264k free,     3936k buffers
Swap:   409616k total,        0k used,   409616k free,    32044k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 2793 tobala    20   0  2448 1140  920 R  1.9  0.3   0:00.28 top
    1 root      20   0  1904  776  564 S  0.0  0.2   0:07.81 init
    2 root      15  -5     0    0    0 S  0.0  0.0   0:00.02 kthreadd
    3 root      RT  -5     0    0    0 S  0.0  0.0   0:00.00 migration/0
    4 root      15  -5     0    0    0 S  0.0  0.0   0:00.00 ksoftirqd/0
    5 root      RT  -5     0    0    0 S  0.0  0.0   0:00.00 watchdog/0
    6 root      15  -5     0    0    0 S  0.0  0.0   0:00.01 events/0
    7 root      15  -5     0    0    0 S  0.0  0.0   0:00.00 khelper
    8 root      RT  -5     0    0    0 S  0.0  0.0   0:00.00 kstop/0
    9 root      15  -5     0    0    0 S  0.0  0.0   0:00.00 kintegrityd/0
   10 root      15  -5     0    0    0 S  0.0  0.0   0:00.01 kblockd/0
   11 root      15  -5     0    0    0 S  0.0  0.0   0:00.00 kacpid
   12 root      15  -5     0    0    0 S  0.0  0.0   0:00.00 kacpi_notify
   13 root      15  -5     0    0    0 S  0.0  0.0   0:00.00 cqueue
   14 root      15  -5     0    0    0 S  0.0  0.0   0:00.02 ata/0
   15 root      15  -5     0    0    0 S  0.0  0.0   0:00.00 ata_aux
   16 root      15  -5     0    0    0 S  0.0  0.0   0:00.00 ksuspend_usbd
}}}

''[註]'' -d : Delay time interval

''以批次方式, 顯示執行中程序''
{{{
$ top  -bin  2  -d 1  >pid.txt
$ cat pid.txt
top - 23:35:54 up 26 min,  1 user,  load average: 0.00, 0.01, 0.00
Tasks:  60 total,   1 running,  59 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.6%us,  4.1%sy,  0.0%ni, 94.8%id,  0.5%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:    379900k total,    60652k used,   319248k free,     3956k buffers
Swap:   409616k total,        0k used,   409616k free,    32052k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 2804 tobala    20   0  2444 1044  840 R  5.2  0.3   0:00.10 top


top - 23:35:55 up 26 min,  1 user,  load average: 0.00, 0.01, 0.00
Tasks:  60 total,   1 running,  59 sleeping,   0 stopped,   0 zombie
Cpu(s):  1.0%us, 23.3%sy,  0.0%ni, 75.7%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:    379900k total,    61040k used,   318860k free,     3956k buffers
Swap:   409616k total,        0k used,   409616k free,    32052k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 2804 tobala    20   0  2452 1132  916 R  2.9  0.3   0:00.13 top
}}}

''[註]''
-b : Batch mode operation
-i : Idle Processes toggle
-n : Number of iterations

<<toBalaNotes "pid">>


///%pid
//%/
''參考文章''
1. Learn Linux, 101: The Linux command line
http://www.ibm.com/developerworks/linux/library/l-lpic1-v3-103-1/index.html

{{item1{echo 命令基本操作}}}
The ''echo'' command prints (or echos) its arguments to the terminal 

{{{
$ echo Word
Word
$ echo A phrase
A phrase
}}}

''練習'' : 以下命令有何不同 ?
{{{
$ echo Where     are   my   spaces?

$ echo "Here     are   my   spaces." 
}}}

{{item1{echo 命令進階操作}}}
''echo escaped characters''
The echo command has a couple of options. Normally echo will append a trailing new line character to the output. Use the ''-n'' option to suppress this. Use the ''-e'' option to enable certain backslash escaped characters to have special meaning. 

|''Escape''|''sequence	Function''|
|\a|Alert (bell)|
|\b|Backspace|
|\c|Suppress trailing newline (same function as -n option)|
|\f|Form feed (clear the screen on a video display)|
|\n|New line|
|\r|Carriage return|
|\t|Horizontal tab|

''操作如下''
{{{
$ echo -n No new line
No new line$ echo -e "No new line\c"
No new line$ echo "A line with a typed
> return"
A line with a typed
return
$ echo -e "A line with an escaped\nreturn"
A line with an escaped
return

$ echo "A line with an escaped\nreturn but no -e option"
A line with an escaped\nreturn but no -e option

$ echo -e Doubly escaped\\n\\tmetacharacters                (因顯示字串前後沒有雙引號, 所以 \ 必須前面要再加一個 \)
Doubly escaped
        metacharacters

$ echo Backslash \
> followed by newline \
> serves as line continuation.
Backslash followed by newline serves as line continuation.
}}}
<<toBalaNotes "echo">>

{{item1{Linux 命令分類}}}

''1. Account management''
{{{
* quota - to check your network account quota.
* yppasswd - to change your network account password.
* passwd - to change your local password.
* chmod [options] filename - to change file permissions.
}}}

''2. Exiting from a shell prompt (to close a terminal window or to log out)''
{{{
* exit
* or by pressing <ctrl+d> - the general end of text control character.
}}}

''3. File system navigation / directories''
{{{
* pwd [options] - to obtain/print the name of your current/working directory.
* cd [options] [directoryname | ~ | ./ | ../ | - ] - to change your working directory.
* ls [options] directoryname - to list the contents of directories.
* mkdir [options] directoryname - to create new directories.
* rmdir [options] directoryname - to remove/delete directories.
* cp [options] source destination - to copy files and directories.
* mv [options] source destination - to move files and directories.
* rm [options] filenamelist - to remove/delete files.
}}}

''4. Searching for files by name''
{{{
* locate [options] <searchstring>
* find [options] <searchstring>
}}}

''5. Searching through contents of files''
{{{
* grep [options] <searchstring>
}}}

''6. Determining file types''
{{{
* file [options] filename
}}}

''7. Viewing text files''
{{{
* cat [options] filename - to display the file contents without pause or break.
* less [options] filename - to display file contents page by page.
* more [options] filename - to display file contents page by page.
* tail [options] filename - to display the last few lines of a file.
* head [options] filename - to display the first few lines of a file.
}}}

''8. Editing text files''
{{{
* To edit a text file type: editorname filename [&], where editorname could be one of the following: GNU-emacs, vi, joe, pico, etc. (note: change these links to the internal editor site)
}}}

''9. Compressing and decompressing files''
{{{
File extension 	Compression command 	Decompression command
.gz 	gzip 	gunzip or gzip -d
.bz2 	bzip2 or bzip2 -d 	bunzip2
.zip 	zip 	unzip
.Z 	compress 	uncompress
}}}

''10. Reading compressed text files''
{{{
* zless [options] compressedfilename - to display the contents page by page without uncompressing the file.
}}}

''11. Archiving (packaging) files and directories''
{{{
* tar [options] filenamelist archive.tar - to archive files (store and extract). Compression and decompression is available in the following formats: .bz2(.bz) or .gz .
* cpio [options] filenamelist - to copy files to and from an archive.
* zip / unzip [options] archivename.zip filenamelist - to package and unpackeage compressed archives.
* zoo [options] archive filename - to create and maintain collections of files in compressed form.
}}}

''12. Commands for managing print jobs''
{{{
* lpr [options] filenames... - to print files.
* lpq [options] - to check printer que status.
* lprm [options] printjobIDs - to cancel print jobs.
}}}

''13. Using floppy diskettes and CD-ROMs''
{{{
* mount /mnt/floppy - to mount floppies.
* mount /mnt/cdrom - to mount CD-ROMs.
* umount /mnt/floppy - to unmount floppies.
* umount /mnt/cdrom - to unmount CD-ROMs.
* mkisofs [options] filename [specifications] - to create a binary ISO image file.
* cdrecord [options] tracks... - to record audio or data compact discs.
* mtools - alternative file manipulation commands for DOS disks. Instead of mounting a disk, with the mount command as above, and using standard Linux commands like cp, ls, mv, etc. one can use the mtool commands to manipulate files. Consult man mtools for information about these commands.
}}}

''14. Remote access''
{{{
* ssh [options] user[@host] - to make secure shell connections.
* scp [options] [user1@host1]:filenames... user2@host2:filenames... - to securely copy individual files.
* sftp [options] [user]@host - to start a powerful interactive secure file transfer program.
}}}

''15. To run applications in the background''
{{{
* nohup commandname [arguments] - to run a command, with a non-tty output, that should continue running after exiting the prompt.
* nice [options] commandname [arguments] - to run a program with modified scheduling priority.
* renice priority [options] - to alter the priority of a running process.
* & - to put a job in the background (for example emacs mytext.txt &).
* bg [jobspec] - to resume the suspended job jobspec in the background as if it had been started with &.
* fg [jobspec] - to put the specified job in the foreground (to make it the current job).
}}}

''16. Useful system commands''
{{{
* ps [options] - to display active proccesses.
* kill [options] processID - to send a signal to a process ("kill" is a misnomer).
* top [options] - to display top CPU processes.
* free [options] - to display information about free and used memory on the system.
* df [options] file(system)name - to get information on filesystem disk space usage.
* du [options]filename - to estimate file space usage.
}}}

''17. Command line history, I/O redirection, and piping''
{{{
* history [options] - to display the command line history.
* <tab> key - to complete a partially typed file/directory name or command.
* <↑> / <↓> keys - to navigate the command history buffer.
* ; - to separate multiple commands on a single line. Ffor example command1 ; command2.
* >,>> - to redirect the output of a command. For example ls -la directoryname > myfile.txt will write the output of the ls command to the file myfile.txt (and not to the screen!) while overwriting any previous contents of the file. If >> is used instead of > the original contents of the file myfile.txt will not be ereased but the output of ls will be appended to it.
* < - to use a specific file as an input to a command. For example cpio [options] < filenamelistfile.txt
* | - to pipe the output of one command to another command. Ffor example ls -al directoryname | less.
}}}

''18. Miscellaneous''
{{{
* date [options] - to display and set the system date and time.
* clear - to clear the terminal window.
* reset [options] - to reset the terminal window to its default display settings.
}}}

<<toBalaNotes "2">>


///%echo
//%/

///%2
//%/
{{item1{手動設定 VMware 虛擬主機 MAC 位址 (永久)}}}
VMware 預設的 MAC address 是亂數產生的,對於要控管 MAC address 時並不方便. GUI 裡並不能設定各 網卡 的 MAC addres, 但是可以透過修改 ''設定檔 (*.vmx)'' 的方式來設定.

首先將要修改的 VM ( Virtual Machine ) 關機, 然後開啟該 VM 的 .vmx 設定檔, 找到以下幾行:
{{{
ethernet[x].addressType = "generated"
ethernet[x].generatedAddress = "00:0c:29:xx:xx:xx"
}}}
改成
{{{
ethernet[x].addressType = "static"
ethernet[x].address = "00:50:56:xx:yy:zz" (注意!!前面的 vendor code: 00:50:56 絕對不要改)
}}}
再把下面這行刪掉
{{{
ethernet[x].generatedAddressOffset = "0"
}}}
接下來就可以重新啟動 VM , 這時這台 VM 的 MAC addres 已經是之前手動指定的了.

''[重點]''
In MAC address, XX must be a valid hexadecimal number between ''00h'' and ''3Fh'', and YY and ZZ must be valid hexadecimal numbers between ''00h'' and ''FFh''. Because VMware Workstation virtual machines do not support arbitrary MAC addresses, you must use the above format.

{{item1{Ubuntu 重設 MAC 位址}}}
{{op1{1. Ubuntu 8.04 及以後版本 - 重設 MAC 位址}}}
因網卡的 MAC 位址重新設定, 以至系統啟動後, 沒有網路系統可使用, 避免此問題發生, 在關閉此虛擬主機之前, 請執行以下命令 :
{{{
# sudo rm /etc/udev/rules.d/70-persistent-net.rules
}}}

或

將以下程式段, 加到 ~/.bashrc 這檔案的最後
{{{
ifconfig -a | grep eth0 &>/dev/null
if [ "$?" != "0" ]; then
   read -p "reset MAC ? (y/n) : " ans
   if [ "$ans" == "y" ]; then
      sudo rm /etc/udev/rules.d/70-persistent-net.rules &>/dev/null
      sudo reboot
   fi
   echo ""
fi
}}}

{{op1{2. Ubuntu Server 6.06  系統重設 MAC 位址}}}
''A. 編寫 fixmac 程序檔''
{{{
mac=$(ifconfig -a | grep "HWaddr" | cut -d " " -f 11)
echo "eth0 mac $mac arp 1" > /etc/iftab
}}}

''B. 設定執行權限''
{{{
$ chmod +x fixmac
}}}

''C. 登入後執行 fixmac''
{{{
$ sudo ./fixmac
}}}

{{item1{查詢 MAC 所屬廠商}}}
1. 到 IEEE 網站 (http://standards.ieee.org/develop/regauth/oui/public.html)

[img[img/IEEEMAC01.png]]

2. 輸入 MAC 前三個數字, 進行查詢

[img[img/IEEEMAC02.png]]

[img[img/IEEEMAC03.png]]
''參考文章''
1. The GRUB MBR (Stage 1 MBR 程式碼說明)
http://thestarman.pcministry.com/asm/mbr/GRUB.htm

{{item1{MBR 內容架構}}}
MBR Wikipedia : http://en.wikipedia.org/wiki/Master_boot_record

[img[img/linux/mbr.png]]

{{item1{磁碟分割表}}}

[img[img/linux/diskpartion.png]]

''[註]'' Cylinder, Head 及 Sector 的簡稱為 CHS

{{item1{Linux Disk Editor (lde)}}}
lde 官網 : http://lde.sourceforge.net/

''lde'' is a disk editor for linux, originally written to help recover deleted files. It has a simple ncurses interface that resembles an old version of Norton Disk Edit for DOS. lde is 100 percent free under the Gnu public license. 
{{{
$ sudo apt-get install lde
}}}

{{item1{磁碟內容編輯}}}
{{op1{檢視與修改磁碟磁區}}}

''$ sudo lde /dev/sda''

[img[img/linux/diskedit01.png]]

''按 b 按鍵, 顯示磁區 (sector) 資訊''

[img[img/linux/diskedit02.png]]

''按 Pg Up 或 Pg Dn 檢視 磁區 (sector) 資訊''

[img[img/linux/diskedit03.png]]

''按 F2 鍵, 出現選單, 如在 Putty 視窗中, 請按 Ctrl+O''

[img[img/linux/diskedit04.png]]

<<toBalaNotes "lde">>

{{item1{檔案修改}}}

''1. 載入檔案''
{{{
$ sudo lde hello.class
}}}

[img[img/linux/ldemf01.png]]

''2. 開啟寫入 Flag''

[img[img/linux/ldemf02.png]]

[img[img/linux/ldemf03.png]]

[img[img/linux/ldemf04.png]]

''3. 修改內容''

[img[img/linux/ldemf05.png]]

[img[img/linux/ldemf06.png]]

<<toBalaNotes "modsec">>


///%lde
//%/

///%modsec
//%/
''參考文章''
1. SSH tips and tricks. Dead or unresponsive ssh session
http://www.onlinehowto.net/Tutorials/SSH/SSH-tips-and-tricks-Dead-or-unresponsive-ssh-session/1271

{{item1{Linux 連接命令}}}
__{{op1{ssh 命令}}}__
ssh (SSH client) is a program for logging into a remote machine and for executing commands on a remote machine.  It is intended to replace rlogin and rsh, and provide secure encrypted communications between two untrusted hosts over an insecure network.

''登入遠端 SSH 主機''
{{{
# ssh student@140.137.214.55
The authenticity of host 'kvmnat (140.137.214.55)' can't be established.
RSA key fingerprint is f8:ae:67:0e:f0:e0:3e:bb:d9:88:1e:c9:2e:62:22:72.
Are you sure you want to continue connecting (yes/no)? yes
student@140.137.214.252's password: 
}}}

''遠端執行命令''
{{{
# ssh root@140.137.214.252 ls -al
root@140.137.214.252's password: 
總計 1597540
drwx------  8 root root       4096 2010-09-15 11:33 .
drwxr-xr-x 23 root root       4096 2010-09-04 18:24 ..
drwxr-xr-x  2 root root       4096 2010-09-14 22:42 172.30.100.0
-rw-r--r--  1 root root 1634836713 2010-09-15 11:32 172.30.100.0.zip
drwxrwxrwx 11  501 root       4096 2010-09-04 18:24 apache-couchdb-1.0.1
-rw-r--r--  1 root root     986352 2010-08-12 02:29 apache-couchdb-1.0.1.tar.gz
drwx------  2 root root       4096 2010-09-03 19:47 .aptitude
-rw-------  1 root root       5484 2010-09-15 11:54 .bash_history
-rw-r--r--  1 root root       3161 2010-09-14 23:16 .bashrc
drwx------  2 root root       4096 2010-09-03 19:54 .cache
drwxr-xr-x  2 root root       4096 2010-09-03 19:47 .debtags
-rw-r--r--  1 root root        140 2010-04-23 17:45 .profile
drwxr-xr-x  2 root root       4096 2010-09-03 19:56 .uml
}}}

__{{op1{scp 命令}}}__
scp copies files between hosts on a network.  It uses ssh(1) for data transfer, and uses the same authentication and provides the same security as ssh(1).  Unlike rcp(1), scp will ask for passwords or passphrases if they are needed for authentication.

''將資料由本機上傳到遠端主機上去''
{{{
# scp /etc/rc.local student@140.137.214.46:/home/student/
student@140.137.214.46's password: <== 這裡請輸入密碼啊!
rc.local                  100%  620     0.6KB/s   00:00
}}}
上例在說明,我將本機 /etc/crontab 這個檔案傳送給 student 這個使用者, 而這個使用者是在 "140.137.214.46" 那部主機上面喔!
仔細看一下,會有一個傳輸資料的訊息跑出來喔!

''將資料由遠端主機下載到本機上''
{{{
# scp student@140.137.214.46:~/.bashrc  .
}}}
上例則是在說明,我要將 140.137.214.46 那部機器上的 student 這個使用者 ,他家目錄下的 .bashrc 複製到我的機器上!

@@color:red;''[注意]''@@ 如執行 scp 命令, 出現 "Read-only file system" 這錯誤訊息, 代表檔案無法 ''複製'' 或 ''覆蓋'', 原因是 "目地主機" 的檔案系統, 被設成 read-only, 實際例子 : 在 Linux KVM 系統, 執行 Restore Saved Machine 後, 虛擬主機的檔案系統被設成 Read Only

<<toBalaNotes "ssh">>

{{item1{Windows 連接軟體 : Putty}}}
官方網頁: http://chiark.greened.org.uk/~sgtatham/putty/

putty.exe 是一個可在 Windows 平台上 ssh 連線的一套免費軟體, 相容於 Windows 95, 98, ME, NT, 2000, XP and Vista

{{op1{1. 下載 Putty}}}
   
下載網址 : http://chiark.greenend.org.uk/~sgtatham/putty/download.html

{{op1{2. 啟動 Putty 與連接}}}

''啟動 Putty 程式''

[img[img/putty/putty01.png]]

''設定登入帳號名稱''

[img[img/putty/putty02.png]]

''設定中文顯示''

[img[img/putty/putty03.png]]

''儲存設定''

[img[img/putty/putty04.png]]

''第一次連接會收到 OpenSSH Server 送出的 [憑證], 請接受此憑證以建立安全連接''

[img[img/putty/putty05.png]]

''登入系統''

[img[img/putty/putty06.png]]

<<toBalaNotes "puttyconnect">>

///%puttyconnect
//%/


///%ssh
//%/
''參考文章''
1. Network Configuration (必讀)
https://help.ubuntu.com/10.04/serverguide/C/network-configuration.html
2. iT英文─接替既有IP通訊協定的新架構IPv6 
http://www.ithome.com.tw/itadm/article.php?c=67646
3. Rename Network Interface using udev in Debian
http://www.debianhelp.co.uk/udev.htm
4. Simple IPv4/IPv6 Subnet Calculator for Ubuntu Linux – SubNetCalc
http://www.hecticgeek.com/2012/01/simple-ipv4-ipv6-subnet-calculator-ubuntu-linux/
5. Ubuntu 12.04 LTS Precise Pangolin: Networking tips and tricks (很重要)
http://www.sitepoint.com/ubuntu-12-04-lts-precise-pangolin-networking-tips-and-tricks/

{{item1{檢視本機 TCP/IP 資訊}}}
{{{
1. ifconfig  -a                 (IP 位址)
2. netstat  -rn                (Default Gateway)
3. cat   /etc/resolv.conf   (DNS Server 位址)
}}}

{{item1{列出所有網路介面資訊}}}
既使沒有取得 IP 位址, 也會列印網路卡資訊
{{{
# ifconfig -a
}}}

{{item1{顯示網卡資訊}}}
{{{
$ sudo lshw -class network
[sudo] password for student:
  *-network
       description: Ethernet interface
       product: 82545EM Gigabit Ethernet Controller (Copper)
       vendor: Intel Corporation
       physical id: 0
       bus info: pci@0000:02:00.0
       logical name: eth0
       version: 01
       serial: 00:0c:29:81:3e:b4
       size: 1Gbit/s
       capacity: 1Gbit/s
       width: 64 bits
       clock: 66MHz
       capabilities: pm pcix bus_master cap_list rom ethernet physical logical tp 10bt 10bt-fd 100bt 100bt-fd 1000bt-fd autonegotiation
       configuration: autonegotiation=on broadcast=yes driver=e1000 driverversion=7.3.21-k8-NAPI duplex=full firmware=N/A ip=192.168.44.145 latency=0 link=yes mingnt=255 multicast=yes port=twisted pair speed=1Gbit/s
       resources: irq:18 memory:c9020000-c903ffff memory:c9000000-c900ffff ioport:2000(size=64) memory:d8400000-d840ffff
}}}

{{item1{自動取得 IP 位址 (DHCP)}}}
{{{
# sudo nano  /etc/network/interfaces
                :
auto  lo
iface  lo  inet  loopback

auto  eth0
iface  eth0  inet  dhcp
}}}
The first line specifies that the eth0 device should come up automatically when you boot. The second line means that interface (“iface”) eth0 should have an IPv4 address space (replace “inet” with “inet6” for an IPv6 device) and that it should get its configuration automatically from DHCP. Assuming your network and DHCP server are properly configured, this machine's network should need no further configuration to operate properly. The DHCP server will provide the default gateway (implemented via the route command), the device's IP address (implemented via the ifconfig command), and DNS servers used on the network (implemented in the /etc/resolv.conf file.) 

''釋放及重新取得 IP 位址''
{{{
# sudo dhclient eth1
Internet Systems Consortium DHCP Client V3.0.3
Copyright 2004-2005 Internet Systems Consortium.
All rights reserved.
For info, please visit http://www.isc.org/products/DHCP

Listening on LPF/eth1/00:0c:29:98:6a:a3
Sending on   LPF/eth1/00:0c:29:98:6a:a3
Sending on   Socket/fallback
DHCPDISCOVER on eth1 to 255.255.255.255 port 67 interval 7
DHCPOFFER from 192.168.0.1
DHCPREQUEST on eth1 to 255.255.255.255 port 67
DHCPACK from 192.168.0.1
bound to 192.168.0.163 -- renewal in 294754 seconds.
}}}

{{item1{手動設定 IP 位址}}}
{{{
# sudo  nano  /etc/network/interfaces
                        :
iface  eth1  inet  static
      address  192.168.200.11
      netmask  255.255.255.0
      gateway  192.168.200.2
      dns-nameservers  168.95.1.1
}}}

''[註]'' 在 Ubuntu 12.04 這版本, dns-nameservers 這個設定可正常運作

''重新啟動網卡''
{{{
# sudo /etc/init.d/networking restart
}}}

{{item1{設定 DNS Client}}}
{{{
# sudo  nano  /etc/resolv.conf
search com
nameserver 204.11.126.131
nameserver 64.125.134.133
nameserver 64.125.134.132
nameserver 208.185.179.218
}}}
The ''search'' key specifies the string which will be appended to an incomplete hostname. Here, we have configured it to com. So, when we run: ping ubuntu it would be interpreted as ping ubuntu.com.

The ''nameserver'' key specifies the nameserver IP address. It will be used to resolve a given IP address or hostname. This file can have multiple nameserver entries. The nameservers will be used by the network query in the same order. 

[img[img/warning.png]] If the DNS server names are retrieved dynamically from DHCP or PPPoE (retrieved from your ISP), do not add nameserver entries in this file. It will be overwritten. 

''Making permanent changes to resolv.conf under Ubuntu''
After googling some more. I think i found a better way to solve this problem. And probably the only way to solve this. No need to install any extra software. 
Just edit the dhclient config file.

change the following lines in ''/etc/dhcp3/dhclient.conf''
{{{
supersede domain-name “example.com”
prepend domain-name-server xxx.xxx.xxx.1, xxx.xxx.xxx.2
}}}

{{item1{設定 Default Gateway (暫時)}}}
{{{
# route add default gw 140.137.214.22
}}}

''顯示 Routing Table''
{{{
# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
172.30.100.0    0.0.0.0         255.255.255.0   U     0      0        0 virbr2
140.137.214.0   0.0.0.0         255.255.255.0   U     0      0        0 br0
192.168.122.0   0.0.0.0         255.255.255.0   U     0      0        0 virbr0
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 br0
0.0.0.0         140.137.214.22  0.0.0.0         UG    0      0        0 br0
}}}

''刪除 Default Gateway''
{{{
# route del default gw 140.137.214.22
}}}

<<toBalaNotes "tcpip">>
{{item1{TCP/IP 客戶端自選 Port 範圍 - Ephermal port range}}}
以下是 Ubuntu 12.04 的 TCP/IP 客戶端自選 Port 範圍, 命令如下 :
{{{
student@UB1204:~$ cat /proc/sys/net/ipv4/ip_local_port_range
32768	61000
}}}
{{item1{顯示本機開啟的 TCP/UDP Port 及對應的 Program name}}}
必須是 root 身份, 才能執行 netstat 的 -p 參數
{{{
# netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:5037          0.0.0.0:*               LISTEN      6870/adb        
tcp        0      0 172.30.100.1:53         0.0.0.0:*               LISTEN      1261/dnsmasq    
tcp        0      0 192.168.122.1:53        0.0.0.0:*               LISTEN      1212/dnsmasq    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1544/sshd       
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      1181/cupsd      
tcp        0      0 127.0.0.1:6010          0.0.0.0:*               LISTEN      4631/sshd: nx@notty
tcp6       0      0 :::139                  :::*                    LISTEN      881/smbd        
tcp6       0      0 :::22                   :::*                    LISTEN      1544/sshd       
tcp6       0      0 ::1:631                 :::*                    LISTEN      1181/cupsd      
tcp6       0      0 ::1:6010                :::*                    LISTEN      4631/sshd: nx@notty
tcp6       0      0 :::445                  :::*                    LISTEN      881/smbd        
udp        0      0 0.0.0.0:5353            0.0.0.0:*                           937/avahi-daemon: r
udp        0      0 0.0.0.0:40864           0.0.0.0:*                           937/avahi-daemon: r
udp        0      0 172.30.100.1:53         0.0.0.0:*                           1261/dnsmasq    
udp        0      0 192.168.122.1:53        0.0.0.0:*                           1212/dnsmasq    
udp        0      0 0.0.0.0:67              0.0.0.0:*                           1212/dnsmasq 
}}}

''netstat 簡易手冊''
{{{
$ netstat --help
usage: netstat [-veenNcCF] [<Af>] -r         netstat {-V|--version|-h|--help}
       netstat [-vnNcaeol] [<Socket> ...]
       netstat { [-veenNac] -i | [-cnNe] -M | -s }

        -r, --route              display routing table
        -i, --interfaces         display interface table
        -g, --groups             display multicast group memberships
        -s, --statistics         display networking statistics (like SNMP)
        -M, --masquerade         display masqueraded connections

        -v, --verbose            be verbose
        -n, --numeric            don't resolve names
        --numeric-hosts          don't resolve host names
        --numeric-ports          don't resolve port names
        --numeric-users          don't resolve user names
        -N, --symbolic           resolve hardware names
        -e, --extend             display other/more information
        -p, --programs           display PID/Program name for sockets
        -c, --continuous         continuous listing

        -l, --listening          display listening server sockets
        -a, --all, --listening   display all sockets (default: connected)
        -o, --timers             display timers
        -F, --fib                display Forwarding Information Base (default)
        -C, --cache              display routing cache instead of FIB

  <Socket>={-t|--tcp} {-u|--udp} {-w|--raw} {-x|--unix} --ax25 --ipx --netrom
  <AF>=Use '-6|-4' or '-A <af>' or '--<af>'; default: inet
  List of possible address families (which support routing):
    inet (DARPA Internet) inet6 (IPv6) ax25 (AMPR AX.25)
    netrom (AMPR NET/ROM) ipx (Novell IPX) ddp (Appletalk DDP)
    x25 (CCITT X.25)
}}}
{{item1{在 Ubuntu 系統重設 MAC 位址}}}
在 Ubuntu 系統中, 如重設網卡的 MAC  位址, 請必須執行以下步驟 (只適用 Ubuntu) :
{{{
$ sudo rm /etc/udev/rules.d/70-persistent-net.rules
}}}

或

將以下程式段, 加到 ~/.bashrc 這檔案的最後
{{{
$ nano .bashrc
ifconfig -a | grep eth0 &>/dev/null
if [ "$?" != "0" ]; then
   read -p "reset MAC ? (y/n) : " ans
   if [ "$ans" == "y" ]; then
      sudo rm /etc/udev/rules.d/70-persistent-net.rules &>/dev/null
      sudo reboot
   fi
   echo ""
fi
}}}

{{item1{Change your Network Card MAC Address on Ubuntu}}}
{{{
auto eth0
iface eth0 inet dhcp
        hwaddress ether 01:02:03:04:05:06
}}}

{{item1{使用 MAC 找 IP 位址}}}

''1. Clears out your arp cache''
{{{
$ ip neigh flush all > /dev/null; 
}}}

''2. pings all of subnet''
{{{
$ sudo apt-get install fping
$ fping -c 1 -g -q 140.137.214.0/24 2> /dev/null
}}}

''3. 搜尋 MAC 位址''
{{{
# arp -n | grep "52:54:00:d1:cf:19"
140.137.214.59           ether   52:54:00:d1:cf:19   C                     br0
}}}

{{item1{單網卡多個 IP (IP Alias)}}}
Your ethernet configuration is located in a file called ''/etc/network/interfaces''. If you reboot system you will lost your alias. To make it permanent you need to add it network configuration file:
{{{
$ sudo nano /etc/network/interfaces
}}}
Append the following configuration:
{{{
auto eth0:0
iface eth0:0 inet static
name Ethernet alias LAN card
address 192.168.1.11
netmask 255.255.255.0
broadcast 192.168.1.255
network 192.168.1.0
}}}
Save the file and restart system or restart the network:
{{{
$ sudo /etc/init.d/networking restart 
}}}

<<toBalaNotes "ipalias">>

///%tcpip
//%/

///%ipalias
//%/
1. Gnome 桌面網站

http://gnome-look.org/

2. 安裝以下套件, 在選單中, 才會出現 "進階設定選項", 此工具程式主要用來設定桌面
{{{
$ sudo apt-get install gnome-tweak-tool
}}}

3. 安裝 Orion 桌面
{{{
$ sudo apt-add-repository ppa:satyajit-happy/themes

$ sudo apt-get update

$ sudo apt-get install orion-gtk-theme

$ gsettings set org.gnome.desktop.interface gtk-theme 'Orion'

$ gconftool-2 --set --type string /apps/metacity/general/theme 'Orion'
}}}

4. 將視窗按鈕移到右邊
{{{
gconftool -s /apps/metacity/general/button_layout -t string menu:minimize,maximize,close 
}}}
<<toBalaNotes "1">>
{{item1{Ubuntu Tweak}}}
1. 到下列網址, 下在 UbuntuTweak 安裝套件
http://ubuntu-tweak.com

///%1
//%/
本文網址 : http://tombuntu.com/index.php/2010/01/01/enable-automatic-login-in-ubuntu-9-10-server/

Ubuntu makes it easy to enable automatic login if you’re using a login manager such as GDM. I was recently setting up a minimal Ubuntu 9.10 system with an LXDE desktop and no GDM. Here’s how I enabled automatic login.

''[註]''  This was tested on Ubuntu 9.10. Previous versions of Ubuntu require different procedures because of changes to the way Ubuntu boots.

Open /etc/init/tty1.conf as root:
{{{
$ sudo nano /etc/init/tty1.conf
}}}
Change the last line of this file to (where USERNAME is the username of the user you want to log in):
{{{
exec /bin/login -f USERNAME < /dev/tty1 > /dev/tty1 2>&1
}}}
Reboot, and the user you chose should be logged in automatically after boot. If something goes wrong, you can switch to a different TTY with CTRL+ALT+F2 and log in normally.

If you want this user to be logged into a graphical environment instead of just a shell, there’s more work to be done. Open your user’s .bashrc file:
{{{
nano ~/.bashrc

Add the following to the end of the file:
if [ $(tty) == "/dev/tty1" ]; then
startx
fi
}}}
This code will start X (the graphical environment) whenever the user logs in on TTY1. You can add more code after startx that will be executed if the user logs out of X.

<<toBalaNotes "1">>


///%1
//%/
<<forEachTiddler 
 where
   'tiddler.tags.contains("toBala")'
>>
{{op1{考前苦悶是暫存檔}}}

{{item1{LPIC 101}}}
@@color:blue;<<forEachTiddler
    where
        'tiddler.tags.contains("lpic101")'
    sortBy
      'tiddler.title'
      ascending
    write
        '(index < 200) && (index >=0)? (index+1) + ". [["+tiddler.title+"]]\n" : ""'
>>@@
{{item1{LPIC 102}}}
@@color:blue;<<forEachTiddler
    where
        'tiddler.tags.contains("lpic102")'
    sortBy
      'tiddler.title'
      ascending
    write
        '(index < 200) && (index >=0)? (index+1) + ". [["+tiddler.title+"]]\n" : ""'
>>@@
官方網站 : http://www.nano-editor.org 
本文網址 : http://www.gentoo.org/doc/en/nano-basics-guide.xml

{{item1{nano 操作}}}
{{op1{Opening and creating files}}}
Opening and creating files is simple in nano, simply type:
{{{
# nano filename
}}}

{{op1{Saving and exiting}}}
If you want to save the changes you've made, press ''Ctrl+O''. To exit nano, type ''Ctrl+X''. If you ask nano to exit from a modified file, it will ask you if you want to save it. Just press N in case you don't, or Y in case you do. It will then ask you for a filename. Just type it in and press Enter.

If you accidentally confirmed that you want to save the file but you actually don't, you can always cancel by pressing ''Ctrl+C'' when you're prompted for a filename.

{{op1{Cutting and pasting}}}
To cut a single line, you use ''Ctrl+K'' (hold down Ctrl and then press K). The line disappears. To paste it, you simply move the cursor to where you want to paste it and punch ''Ctrl+U''. The line reappears. To move multiple lines, simply cut them with several Ctrl+Ks in a row, then paste them with a single Ctrl+U. The whole paragraph appears wherever you want it.

If you need a little more fine-grained control, then you have to mark the text. Move the cursor to the beginning of the text you want to cut. Hit Ctrl+6 (or Alt+A). Now move your cursor to the end of the text you want to cut: the marked text gets highlighted. If you need to cancel your text marking, simply hit Ctrl+6 again. Press Ctrl+K to cut the marked text. Use Ctrl+U to paste it.

''[註]'' Alt + 6 = Copy the current line

{{op1{Searching for text}}}
Searching for a string is easy as long as you think "WhereIs" instead of "Search". Simply hit ''Ctrl+W'', type in your search string, and press Enter. To search for the same string again, hit ''Alt+W''.

Note: In nano's help texts the Ctrl-key is represented by a caret (^), so Ctrl+W is shown as ^W, and so on. The Alt-key is represented by an M (from "Meta"), so Alt+W is shown as M-W.

{{item1{操作練習}}}
''設定 Bash 提示字串格式 (.bashrc)''
{{{
# nano  ~/.bashrc
            :
export PS1=“[\u@\h::\w]#  “   
}}}

''設定 Bash 提示字串顏色''
{{{
export PS1="\[\033[01;32m\]\u@\h: "
}}}

在 bash 中,內定的 prompt 是單色的,所以很難分辨出內容和 prompt,有沒有改善的方式呢?

很簡單,只要將個人 home 目錄下的 .bashrc 中的 
{{{
# Comment in the above and uncomment this below for a color prompt
#PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
}}}
改為
{{{
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
}}}
也就是將前面的 # 符號 uncomment 掉即可。

再啟動一個 terminal 你會發現 prompt 的顏色改變了,這樣是否容易辨識多了。

至於顏色的設定方面,可參考以下兩個連結:
1. http://networking.ringofsaturn.com/Unix/Bash-prompts.php
2. http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html 

<<toBalaNotes "nano">>

{{item1{nano 關鍵文字顏色設定檔}}}
參考網址 : http://how-to.wikia.com/wiki/How_to_use_syntax_highlighting_with_the_GNU_nano_text_editor

在 ''/usr/share/nano'' 目錄中, 已存在各種檔案格式的語法設定檔, 例 java.nanorc, html.nanorc,...

''1. 列出所有設定檔''
{{{
$ ls -al /usr/share/nano
總計 120
drwxr-xr-x  2 root root 4096 2010-09-16 12:08 .
drwxr-xr-x 99 root root 4096 2010-09-16 12:11 ..
-rw-r--r--  1 root root  783 2010-02-02 10:30 asm.nanorc
-rw-r--r--  1 root root 1504 2010-02-02 10:30 awk.nanorc
-rw-r--r--  1 root root 1499 2010-02-02 10:30 c.nanorc
-rw-r--r--  1 root root  331 2010-02-02 10:30 css.nanorc
-rw-r--r--  1 root root  680 2010-02-02 10:30 debian.nanorc
-rw-r--r--  1 root root 2032 2010-02-02 10:30 fortran.nanorc
-rw-r--r--  1 root root 3139 2010-02-02 10:30 gentoo.nanorc
-rw-r--r--  1 root root  723 2010-02-02 10:30 groff.nanorc
-rw-r--r--  1 root root  124 2010-02-02 10:30 html.nanorc
-rw-r--r--  1 root root  610 2010-02-02 10:30 java.nanorc
-rw-r--r--  1 root root  248 2010-02-02 10:30 makefile.nanorc
-rw-r--r--  1 root root  264 2010-02-02 10:30 man.nanorc
-rw-r--r--  1 root root   95 2010-02-02 10:30 mutt.nanorc
-rw-r--r--  1 root root 6137 2010-02-02 10:30 nano-menu.xpm
-rw-r--r--  1 root root 1088 2010-02-02 10:30 nanorc.nanorc
-rw-r--r--  1 root root 1696 2010-02-02 10:30 objc.nanorc
-rw-r--r--  1 root root  791 2010-02-02 10:30 ocaml.nanorc
-rw-r--r--  1 root root  242 2010-02-02 10:30 patch.nanorc
-rw-r--r--  1 root root 1438 2010-02-02 10:30 perl.nanorc
-rw-r--r--  1 root root  687 2010-02-02 10:30 php.nanorc
-rw-r--r--  1 root root  682 2010-02-02 10:30 pov.nanorc
-rw-r--r--  1 root root  527 2010-02-02 10:30 python.nanorc
-rw-r--r--  1 root root 1475 2010-02-02 10:30 ruby.nanorc
-rw-r--r--  1 root root  691 2010-02-02 10:30 sh.nanorc                        (定義 .sh 關鍵文字顏色)
-rw-r--r--  1 root root 2110 2010-02-02 10:30 tcl.nanorc
-rw-r--r--  1 root root  133 2010-02-02 10:30 tex.nanorc
-rw-r--r--  1 root root  260 2010-02-02 10:30 xml.nanorc
}}}

''2. java.nanorc 內容''
{{{
## Here is an example for Java.
##
syntax "java" "\.java$"
color green "\<(boolean|byte|char|double|float|int|long|new|short|this|transient|void)\>"
color red "\<(break|case|catch|continue|default|do|else|finally|for|if|return|switch|throw|try|while)\>"
color cyan "\<(abstract|class|extends|final|implements|import|instanceof|interface|native|package|private|protected|public|static|strictfp|super|synchronized|throws|volatile)\>"
color red ""[^"]*""
color yellow "\<(true|false|null)\>"
color blue "//.*"
color blue start="/\*" end="\*/"
color brightblue start="/\*\*" end="\*/"
color ,green "[[:space:]]+$"
}}}

''Explaining how syntax highlight work''
You first need to specify a line with the name of the syntax and the files that you want to be highlighted by your syntax. Adding a line like :
{{{
syntax "c-file" "\.(c|h)$"
}}}
means that you want all the .c and .h files to be highlighted with the content that you specify after this line, with some regular expressions. For example, add the following line after the previous line to highlight all the integer numbers (positive or negative) in red :
{{{
color red "\<[-+]?([1-9][0-9]*|0)?\>"
}}}

{{item1{取消 .sh 關鍵文字顏色}}}

''1. 編輯 /etc/nanorc 設定檔''
{{{
$ sudo nano /etc/nanorc
}}}

''2. 註解下圖指定的設定''

[img[img/linux/nanorc.png]]

<<toBalaNotes "3">>

///%nano
//%/

///%3
//%/
{{op1{1. 檢視更新套件資料庫的設定檔 (/etc/apt/sources.list)}}}

''$ sudo  nano  /etc/apt/sources.list''
{{{
# 
# deb cdrom:[Ubuntu-Server 9.04 _Jaunty Jackalope_ - Release i386 (20090421.1)]/ jaunty main restricted

#deb cdrom:[Ubuntu-Server 9.04 _Jaunty Jackalope_ - Release i386 (20090421.1)]/ jaunty main restricted
# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
# newer versions of the distribution.

deb http://tw.archive.ubuntu.com/ubuntu/ jaunty main restricted
deb-src http://tw.archive.ubuntu.com/ubuntu/ jaunty main restricted

## Major bug fix updates produced after the final release of the
## distribution.
deb http://tw.archive.ubuntu.com/ubuntu/ jaunty-updates main restricted
deb-src http://tw.archive.ubuntu.com/ubuntu/ jaunty-updates main restricted

## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team. Also, please note that software in universe WILL NOT receive any
## review or updates from the Ubuntu security team.
deb http://tw.archive.ubuntu.com/ubuntu/ jaunty universe
deb-src http://tw.archive.ubuntu.com/ubuntu/ jaunty universe
deb http://tw.archive.ubuntu.com/ubuntu/ jaunty-updates universe
deb-src http://tw.archive.ubuntu.com/ubuntu/ jaunty-updates universe

## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu 
## team, and may not be under a free licence. Please satisfy yourself as to 
## your rights to use the software. Also, please note that software in 
## multiverse WILL NOT receive any review or updates from the Ubuntu
## security team.
deb http://tw.archive.ubuntu.com/ubuntu/ jaunty multiverse
deb-src http://tw.archive.ubuntu.com/ubuntu/ jaunty multiverse
deb http://tw.archive.ubuntu.com/ubuntu/ jaunty-updates multiverse
deb-src http://tw.archive.ubuntu.com/ubuntu/ jaunty-updates multiverse

## Uncomment the following two lines to add software from the 'backports'
## repository.
## N.B. software from this repository may not have been tested as
## extensively as that contained in the main release, although it includes
## newer versions of some applications which may provide useful features.
## Also, please note that software in backports WILL NOT receive any review
## or updates from the Ubuntu security team.
# deb http://tw.archive.ubuntu.com/ubuntu/ jaunty-backports main restricted universe multiverse
# deb-src http://tw.archive.ubuntu.com/ubuntu/ jaunty-backports main restricted universe multiverse

## Uncomment the following two lines to add software from Canonical's
## 'partner' repository.
## This software is not part of Ubuntu, but is offered by Canonical and the
## respective vendors as a service to Ubuntu users.
# deb http://archive.canonical.com/ubuntu jaunty partner
# deb-src http://archive.canonical.com/ubuntu jaunty partner

deb http://security.ubuntu.com/ubuntu jaunty-security main restricted
deb-src http://security.ubuntu.com/ubuntu jaunty-security main restricted
deb http://security.ubuntu.com/ubuntu jaunty-security universe
deb-src http://security.ubuntu.com/ubuntu jaunty-security universe
deb http://security.ubuntu.com/ubuntu jaunty-security multiverse
deb-src http://security.ubuntu.com/ubuntu jaunty-security multiverse
}}}

''[註 ]'' 如 http://tw.archive.ubuntu.com/ubuntu/ 網站無法正常運作, 請改成 http://archive.ubuntu.com/ubuntu/ 這網址

{{op1{2. 更新套件資料庫}}}
{{{
[profx@ubuntu] sudo  apt-get  update      (更新套件清單)
}}}
[img[img/ubuntu9.04/update.png]]

{{op1{3. 升級已安裝套件 (包括 kernel)}}}
{{{
[profx@ubuntu] sudo  apt-get  upgrade    (更新已安裝套件)
}}}
[img[img/ubuntu9.04/upgrade.png]]
<<toBalaNotes "update">>

///%update
//%/
<<timeline>>
{{item1{檢查 ~/bin 目錄存不存在}}}
{{{
$ test -e ./abc
$ echo $?
1                           #  1 代表不存在

$ mkdir abc
$ test -e ./abc
$ echo $?
0
}}}

''[練習 1]'' 下式執行結果為何 ?
{{{
$ test -e ./abc && echo "exist"
}}}

''[練習 2]'' 下式執行結果為何 ?
{{{
$ test -e ./abc && echo "exist" || echo "not exist"
}}}

{{item1{判斷符號 [ ]}}}
{{{
$ [ -z $HOME ] ; echo $?
1
$ [ -n $HOME ] ; echo $?
0
}}}

''實作練習 : 確認 root 執行身份''
{{{
$ nano testroot.sh
#!/bin/bash                                  

w=$(whoami)
[ "$w" != "root" ] &&  echo "need root" && exit 1 

$ chmod +x testroot.sh
$ testroot.sh

$ sudo testroot.sh

}}}

{{item1{Arithmetic Comparisons}}}
|-lt|<|
|-gt|&gt;|
|-le|<=|
|-ge|>=|
|-eq|==|
|-ne|&#33;=|

{{item1{String Comparisons}}}

|=|equal|
|&#33;=|not equal|
|<|less then|
|&gt;|greater then|
|-n s1|string s1 is not empty|
|-z s1|string s1 is empty|

{{item1{Bash File Testing}}}
{{{
-b filename 	Block special file
-c filename 	Special character file
-d directoryname 	Check for directory existence
-e filename 	Check for file existence
-f filename 	Check for regular file existence not a directory
-G filename 	Check if file exists and is owned by effective group ID.
-g filename 	true if file exists and is set-group-id.
-k filename 	Sticky bit
-L filename 	Symbolic link
-O filename 	True if file exists and is owned by the effective user id.
-r filename 	Check if file is a readable
-S filename 	Check if file is socket
-s filename 	Check if file is nonzero size
-u filename 	Check if file set-ser-id bit is set
-w filename 	Check if file is writable
-x filename 	Check if file is executable
}}}
<<toBalaNotes "1">>

///%1
//%/
''參考文章''
1. Revision Controlled Home Directory  Using Git
http://crunchbanglinux.org/wiki/revision_controlled_home_directory

{{item1{目錄權限}}}
{{{
dr-xr-xr-x
}}}

檔案是存放實際資料的所在,那麼目錄主要是儲存啥玩意啊?目錄主要的內容在記錄檔名清單,檔名與目錄有強烈的關連啦! 所以如果是針對目錄時,那個 r, w, x 對目錄是什麼意義呢?

''r (read contents in directory):''

表示具有 ''讀取目錄結構清單'' 的權限,所以當你具有讀取(r)一個目錄的權限時,表示你可以查詢該目錄下的檔名資料。 所以你就可以利用 ls 這個指令將該目錄的內容列表顯示出來!

''w (modify contents of directory):''

這個可寫入的權限對目錄來說,是很了不起的! 因為他表示你具有異動該目錄結構清單的權限,也就是底下這些權限:
{{{
- 建立新的檔案與目錄;
- 刪除已經存在的檔案與目錄(不論該檔案的權限為何!)
- 將已存在的檔案或目錄進行更名;
- 搬移該目錄內的檔案、目錄位置。
}}}
總之,目錄的 w 權限就與該目錄底下的檔名異動有關就對了啦!

''x (access directory):''

'咦!目錄的執行權限有啥用途啊?目錄只是記錄檔名而已,總不能拿來執行吧?沒錯!目錄不可以被執行,目錄的x代表的是使用者能否進入該目錄成為工作目錄的用途! 所謂的工作目錄(work directory)就是你目前所在的目錄啦!舉例來說,當你登入Linux時, 你所在的家目錄就是你當下的工作目錄。而變換目錄的指令是『cd』(change directory) 囉!

''[註]'' 目錄'權限 ''x'' 代表可執行 cd 命令, 目錄權限 ''r'' 代表可執行 ls 命令, 目錄權限 ''w'' 代表可執行 rm 命令 (刪除)

只要是 ''目錄的擁有人'', 並且 ''權限設 744'', 這樣便可以完全控管目錄中的檔案及目錄, 既使目錄中檔案的擁有人是其它人, 一樣可以管理
<<toBalaNotes "1">>

{{item1{目錄權限實作}}}
{{{
[root@linux ~]# cd /tmp 
[root@linux tmp]# mkdir  testing 
[root@linux tmp]# chmod  744  testing 
[root@linux tmp]# touch  testing/testing 
[root@linux tmp]# chmod  600  testing/testing 
# 這個 mkdir 是在建立目錄用的指令!是 make directory 的縮寫。 
# 我們用 root 的身份在 /tmp 底下建立一個名為 testing 的目錄, 
# 並且將該目錄的權限變為 744 ,該目錄的擁有者為 root 喔! 
# 另外, touch 可以用來建立一個沒有內容的檔案,因此, touch testing/testing 
# 可以建立一個空的 /tmp/testing/testing 檔案喔! 

[root@linux tmp]# ls  -al 
drwxr--r-- 2 root root 4096 Jul 14 01:05 testing 
# 仔細看一下,目錄的權限是 744 ,且所屬群組與使用者均是 root 喔! 
# 接下來,我們將 root 的身份切換成為一般身份使用者。 
[root@linux tmp]# useradd  dmtsai  -m -s /bin/bash

[root@linux tmp]# su  dmtsai 
# 那個 su 的指令是用來『變換身份』的一個指令,我們未來會詳細介紹。 
# 注意看,底下這一行中,發現使用者變為 dmtsai 了,而且提示字元變成 $ 了! 
# 也就是說,現在操作系統的人變成 dmtsai 了!那麼 dmtsai 這個人對於 
# /tmp/testing 是屬於 others 的權限,那他可以對 /tmp/testing 幹嘛? 

[dmtsai@linux tmp]$ ls -l  testing/testing            <== 此時身份為 dmtsai 
/bin/ls: testing/testing:Permission denied
total 0 

[dmtsai@linux tmp]$ cd  testing                          <== 此時身份為 dmtsai  
cd: testing/: Permission denied 

# 發現了嗎?即使我們具有 r 的權限,但是沒有 x ,所以 
# dmtsai 無法進入 /tmp/testing 喔! 

[dmtsai@linux tmp]$ exit 
[root@linux tmp]# chown  dmtsai  testing 
# 使用 exit 就可以離開 su 的功能了。我們將這個 testing 目錄的擁有者設定為 
# dmtsai ,此時 dmtsai 就成為 owner 了,那麼這個使用者又能幹麻呢? 

[root@linux tmp]# su  dmtsai 
[dmtsai@linux tmp]$ cd  testing             <== 此時身份為 dmtsai 
[dmtsai@linux testing]$ ls  -l                  <== 此時身份為 dmtsai 
-rw------- 1 root root 0 Jul 14 01:13 testing 

# 再切換身份成為 dmtsai ,此時就能夠進入 testing 了!查閱一下內容。 
# 發現了 testing 這個檔案存在喔!權限是只有 root 才能夠存取~ 
# 那我們測試一下能否刪除呢? 
[dmtsai@linux testing]$ rm  testing       <== 此時身份為 dmtsai 
rm: remove write-protected regular empty file `testing'? y 
# 竟然可以刪除!這樣理解了嗎?! 
}}}

''[註]'' Shell 提示字元, 如有 '#' , 代表 root, Shell 提示字元, 如有 '$' , 代表一般使用者

<<toBalaNotes "2">>



///%1
//%/

///%2
//%/
{{item1{撰寫永不停止程式 (第一版)}}}

''$ cd bin''

''$ nano nostop.sh''
{{{
#!/bin/bash

clear
while [ 1 ]
do
  echo -ne "\033[10;10f Hi Chen : "   
  date
done
}}}

''$ chmod +x nostop.sh''

''$ ./nostop.sh''
此時畫面會先清除, 然後在第十行的第十格, 顯示日期與時間, 但是畫面上會看到游標亂跳 (第二版再來修改)

{{item1{中斷第一版程式}}}

按 ''ctrl+c 複合鍵'', 中斷程式執行

[img[img/linux/nostop01.png]]

{{item1{暫停第一版程式}}}

''1. 暫停程式''

按 ctrl+z 複合鍵, 暫停程式執行

[img[img/linux/nostop02.png]]

''2. 重新啟動程式''

輸入 ''fg'' 命令, 重新啟動程式

[img[img/linux/nostop03.png]]

<<toBalaNotes "1">>

{{item1{撰寫永不停止程式 (第二版)}}}

二版程式會 ''隱藏游標'' 及 攔截 ''ctrl+c 按鍵'', 程式如下 : 
{{{
#!/bin/bash

# trap ctrl-c and call ctrl_c()
trap ctrl_c INT

function ctrl_c() {
   echo -e "\n** Trapped CTRL-C"

   # 下式顯示游標
   tput cnorm

   exit 0 
}

clear

# 下式隱藏游標
tput civis

while [ 1 ]
do
  echo -ne "\033[10;10f Hi Chen : "   
  date
done
}}}

{{item1{直接中斷第二版程式}}}

按 ''ctrl+c 複合鍵'', 中斷程式執行

[img[img/linux/nostop04.png]]

{{item1{間接中斷第二版程式}}}

''1. 暫停程式''

按 ctrl+z 複合鍵, 暫停程式執行, 使用 ps 命令, 檢視 nostop.sh 的 PID

[img[img/linux/nostop05.png]]

''2. 正常中斷程式''

輸入 kill -2 命令, 中斷程式, 需執行 fg 命令, 檢視 nostop.sh 有處理 ctrl+c 

[img[img/linux/nostop06.png]]

''3. 強制中斷程式''

輸入 kill -9 命令,  強制中斷程式, 執行 fg 命令檢視不到任何中斷資訊

[img[img/linux/nostop07.png]]

''kill 命令參數說明''

|代號|名稱|內容|
|1|SIGHUP|啟動被終止的程序,可讓該 PID 重新讀取自己的設定檔,類似重新啟動|
|2|SIGINT|相當於用鍵盤輸入 [ctrl]-c 來中斷一個程序的進行|
|9|SIGKILL|代表強制中斷一個程序的進行,如果該程序進行到一半, 那麼尚未完成的部分可能會有『半產品』產生,類似 vim會有 .filename.swp 保留下來。|
|15|SIGTERM|以正常的結束程序來終止該程序。由於是正常的終止, 所以後續的動作會將他完成。不過,如果該程序已經發生問題,就是無法使用正常的方法終止時, 輸入這個 signal 也是沒有用的。|
|17|SIGSTOP|相當於用鍵盤輸入 [ctrl]-z 來暫停一個程序的進行|
<<toBalaNotes "2">>

///%1
//%/

///%2
//%/
{{item1{建立個人程式執行目錄 (Ubuntu 系統)}}}
因 ~/.profile 會檢查家目錄中, 是否存在 bin 目錄, 如存在會自動幫它加入 PATH 環境變數中
{{{
$ mkdir bin
}}}

{{item1{第一個程式}}}

''$ nano first.sh    (撰寫程式)''
{{{
#!/bin/bash
# Author : power boy
# Date : 2014/0901

abc=$(pwd)
echo $abc

exit 100
}}}

''程式說明''

1. #!/bin/bash    (宣告此程式由 /bin/bash 來執行)

''#!'' can be omitted if the script consists only of a set of generic system commands, using no internal shell directives (環境變數宣告). 這行不寫, 在系統啟動時 (rc.local), 如要執行此程式, 此程式是無法執行.

2. # Author : power boy  (程式備註)

3. abc=$(pwd)    (主體程式)

4. exit 100   (傳回值)

如果程式中, 沒有寫 exit 這命令, 內定傳回值為 1

''$ bash first.sh   (執行程式)''
{{{
/home/tobala
}}}

''$ echo $?     (顯示傳回值)''
{{{
100
}}}

''另外一種執行方式''
{{{
$ chmod +x first.sh
$ ./first.sh
/home/tobala
}}}

''自製 ifconfig 命令''
因程式中, 有使用到 ifconfig 命令, 如只打 ifconfig, 這樣會構成遞迴, 所以必須給絕對目錄 (/sbin/ifconfig), 來執行原先系統命令
{{{
#!/bin/bash
/sbin/ifconfig -a | grep -A1 eth0 | tr -d '\n' | tr -s ' ' | cut -d' ' -f1,5,7
}}}

{{item1{輸入資料}}}

''$ nano add.sh''
{{{
#!/bin/bash
# Author : z

read -p "輸入第一個數字 : " fn
read -p "輸入第二個數字 : " sn

# 檢查 $fn 是否為數字
s=$(echo $fn | tr -d 0-9)
[ -n "$s" ] && echo "$fn 不是數字" && exit 1

total=$(($fn+$sn))
echo $total

exit 0
}}}

''$ bash add.sh''
{{{
輸入第一個數字 : 12
輸入第二個數字 : 23
276
}}}
<<toBalaNotes "bash">>

{{op1{認識 date 命令}}}
{{{
$ date --date='2 days ago' '%Y%m%d'
date: the argument 「%Y%m%d」 lacks a leading `+';
When using an option to specify date(s), any non-option
argument must be a format string beginning with `+'.
請嘗試執行『date --help』來獲取更多資訊。

$ date --date='2 days ago' +%Y%m%d
20090816
}}}

''$ nano CreateFile.sh''
{{{
#!/bin/bash
# Author : y

date1=$(date --date='2 days ago' +%Y%m%d)
touch "$1$date1"

exit 0
}}}


///%bash
//%/
''參考文章''
1. Hashing the executables – a look at hash and type (必讀)
http://crashingdaily.wordpress.com/2008/04/21/hashing-the-executables-a-look-at-hash-and-type/

{{item1{Linux 命令搜尋目錄}}}
External commands are just files in your file system. Basic file management is covered in another article in this series. (See Resources  for the series roadmap). On Linux and UNIX systems, all files are accessed as part of a single large tree that is rooted at /. In our examples so far, our current directory has been the user's home directory. Non-root users usually have a home directory within the /home directory, such as /home/ian, in my case. Root's home is usually /root. If you type a command name, then bash looks for that command on your path, which is a colon-separated list of directories in the ''PATH'' environment variable.

Finding command locations
{{{
$ echo $PATH
/usr/lib/qt-3.3/bin:/usr/kerberos/bin:/usr/lib/ccache:/usr/local/bin:/bin:/usr/bin:/home/ian/bin
$ which bash env zip xclock echo set ls
alias ls='ls --color=auto'
/bin/ls
/bin/bash
/bin/env
/usr/bin/zip
/usr/bin/xclock
/bin/echo
/usr/bin/which: no set in (/usr/lib/qt-3.3/bin:/usr/kerberos/bin:/usr/lib/ccache
:/usr/local/bin:/bin:/usr/bin:/home/ian/bin)

$ type bash env zip xclock echo set ls
bash is hashed (/bin/bash)
env is hashed (/bin/env)
zip is /usr/bin/zip
xclock is /usr/bin/xclock
echo is a shell builtin
set is a shell builtin
ls is aliased to `ls --color=auto'
}}}

Note that the directories in the path mostly end in /bin. This is a common convention, but not a requirement as you can see from /usr/lib/ccache. The which command reported that the ls command is an alias and that the set command could not be found. In this case, we interpret that to mean that it does not exist or that it is a builtin. The type command reports that the ls command is an alias, but it identifies the set command as a shell builtin. It also reports that there is a builtin echo command as well as the one in /bin that was found by which. The commands also produce output in different orders.

We saw that the ls command, used for listing directory contents, is an alias. Aliases are a handy way to configure some commands to use different sets of defaults or to provide an alternate name for a command. In our example, the -&#45;color=tty option causes directory listings to be color coded according to the type of file or directory. Try running dircolors -&#45;print-database to see how the color codings are controlled and which colors are used for what kind of file.

Each of these commands has additional options. Depending on your need, you may use either command. I tend to use which when I am reasonably sure I'll find an executable and I just need its full path specification. I find that type gives me more precise information, which I sometimes need in a shell script.

''Running other commands''

If a command is not in your PATH specification, you may still run it by specifying a path as well as a command name. There are two types of paths that you can use:
{{{
* Absolute paths are those starting with /, such as /bin/bash, /bin/env, etc.
* Relative paths are relative to your current working directory, as reported by the pwd command. These commands do not start with /, but do contain at least one /.
}}}
You may use absolute paths regardless of your current working directory, but you will probably use relative paths only when a command is close to your current directory. Suppose you are developing a new version of the classic "Hello World!" program in a subdirectory of your home directory called mytestbin. You might use the relative path to run your command as mytestbin/hello. There are two special names you can use in a path; a single dot (.) refers to the current directory, and a pair of dots (..) refers to the parent of the current directory. Because your home directory is usually not on your PATH (and generally should not be), you will need to explicitly provide a path for any executable that you want to run from your home directory. For example, if you had a copy of your hello program in your home directory, you could run it using the command ./hello. You can use both . and .. as part of an absolute path, although a single . is not very useful in such a case. You can also use a tilde (~) to mean your own home directory and ~username to mean the home directory of the user named username. Some examples are shown in Listing 18.

Absolute and relative paths
{{{
$ /bin/echo Use echo command rather than builtin
Use echo command rather than builtin

$ /usr/../bin/echo Include parent dir in path
Include parent dir in path

$ /bin/././echo Add a couple of useless path components
Add a couple of useless path components

$ pwd                      # See where we are
/home/ian

$ ../../bin/echo Use a relative path to echo
Use a relative path to echo

$ myprogs/hello         # Use a relative path with no dots
-bash: myprogs/hello: No such file or directory

$ mytestbin/hello        # Use a relative path with no dots
Hello world!

$ ./hello
Hello world!

$ ~/mytestbin/hello      # run hello using ~
Hello world!

$ ../hello                     # Try running hello from parent
-bash: ../hello: No such file or directory
}}}
<<toBalaNotes "search">>
{{item1{which 命令}}}

這個指令是根據 ''PATH'' 這個環境變數, 所設定的路徑,去搜尋 ''執行檔'' 的檔名, 找到後將完整路徑顯示出來
{{{
# which bash
/bin/bash

$ which ifconfig
/sbin/ifconfig

$ which export       # 找不到
}}}

The which command shows you the first occurrence of a command in your path. If you want to know if there are multiple occurrences, then add the -a option as shown in below. 
{{{
$ which -a nano
/usr/bin/nano
/bin/nano     (這是一個 link 檔)

$ ls -al /usr/bin | grep nano
lrwxrwxrwx  1 root   root          9 2010-09-19 19:25 nano -> /bin/nano
}}}

{{item1{type 命令}}}

''type 命令''除了根據 PATH 找檔案, 還會找 bash 內建命令 (export, type, if, while, for,  ...), 這是它與 which 命令的差別
{{{
$ which if                              (which 找不到 bash 內建命令)
$ type if
if is a shell keyword

$ type export
export is a shell builtin

$ type ipconfig                        (根本沒這個命令)
-bash: type: ipconfig:沒有找到

$ type ifconfig                        (type 命令根據 PATH, 找到 ifconfig 命令檔案)
ifconfig is /sbin/ifconfig
}}}

///%search
//%/
{{item1{顯示支援群組}}}
如果我以 tobala 這個使用者的身份登入後,該如何知道我已加入那些群組呢? 很簡單啊,直接輸入 groups 就可以了!注意喔,是 groups 有加 s 呢!結果像這樣:
{{{
$ groups
tobala adm dialout cdrom plugdev lpadmin sambashare admin
}}}

{{item1{建立群組}}}
{{{
# sudo groupadd gama
}}}

{{item1{檢視群組資訊}}}
{{{
$ grep gama /etc/group /etc/gshadow
/etc/group:gama:x:1002:
/etc/gshadow:gama:!::
}}}

{{item1{刪除群組}}}
{{{
# groupdel  gama
}}}

<<toBalaNotes "1">>

{{item1{帳號加入群組}}}
You can use the useradd or usermod commands to add a user to a group. The useradd command creates a new user or update default new user information. The usermod command modifies a user account i.e. it is useful to add user to existing group. There are two types of group. First is primary user group and other is secondary group. All user account related information is stored in /etc/passwd, /etc/shadow and /etc/group files to store user information.

''useradd Example - Add A New User To Secondary Group''

You need to the useradd command to add new users to ''existing group'' (or create a new group and then add user). If group does not exist, create it. The syntax is as follows:
{{{
useradd -G {group-name} username
}}}
In this example, create a new user called vivek and add it to group called developers. First login as a root user (make sure group developers exists), enter:
{{{
# grep developers /etc/group
}}}
Output: developers:x:1124:

If you do not see any output then you need to add group developers using groupadd command:
{{{
# groupadd developers
}}}
Next, add a user called vivek to group developers:
{{{
# useradd -G developers vivek
}}}
Setup password for user vivek:
{{{
# passwd vivek
}}}
Ensure that user added properly to group developers:
{{{
# id vivek
}}}
Output: uid=1122(vivek) gid=1125(vivek) groups=1125(vivek),1124(developers)

Please note that capital G (-G) option add user to a list of supplementary groups. Each group is separated from the next by a comma, with no intervening whitespace. For example, add user jerry to groups admins, ftp, www, and developers, enter:
{{{
# useradd -G admins,ftp,www,developers jerry
}}}

''useradd example - Add a new user to primary group''

To add a user tony to group developers use following command:
{{{
# useradd -g developers tony

# id tony

Sample outputs: uid=1123(tony) gid=1124(developers) groups=1124(developers)
}}}
Please note that small -g option add user to initial login group (primary group). The group name must exist. A group number must refer to an already existing group.

''usermod example - Add a existing user to existing group''

Add existing user tony to ftp supplementary/secondary group with usermod command using -a option ~ i.e. add the user to the supplemental group(s). Use only with -G option :
{{{
# usermod -a -G ftp tony
}}}
Change existing user tony primary group to www:
{{{
# usermod -g www tony
}}}
<<toBalaNotes "2">>
{{item1{初設帳號 (student)}}}
''安裝系統時所產生的帳號, 會自動被加入以下所顯示的群組''
{{{
# cat /etc/group | grep student
adm:x:4:student
dialout:x:20:student
cdrom:x:24:student
plugdev:x:46:student
lpadmin:x:105:student
admin:x:119:student
student:x:1000:
sambashare:x:122:student
}}}

''[註] 加入 admin 群組'', 可獲得 sudo 執行權限


///%1
//%/

///%2
//%/
''參考文章''
1. Grub2 (Ubuntu 官方文件)
https://help.ubuntu.com/community/Grub2
2. How to change Grub2 splash images
網址 : http://linuxers.org/howto/how-change-grub2-splash-images
3. 修改 Ubuntu 9.10 的 GRUB 2 開機畫面
網址 : http://superstanwu.blog.ithome.com.tw/post/775/67160
4. Downgrade Grub 2 to Grub Legacy (Ubuntu 9.10)
http://fordflux.com/blog/linux/downgrade-grub-2/
5. GRUB 2, graphical boot tips to set the desired VGA console mode.
http://harrison3001.blogspot.com/2009/09/grub-2-graphical-boot-tips-to-set.html

{{item1{How to configure Grub2 in Ubuntu 9.10}}}
本文網址 : http://linuxers.org/howto/how-configure-grub2-ubuntu-910

Grub2 is now the default bootloader for most of the distros. It is the next generation of GNU GRUB and aims to be cleaner, safer and more powerful than its previous version Grub legacy. In order to provide such features it was written from scratch and so the way it is configured is quite different from ''Grub Legacy (0.97)''. Since, we linuxers always want to run our systems our way ;), you might be interested in learning how to configure grub2 so that you may comfortably tweak (稍稍調整) and play around with it.

{{op1{GRUB2 Configuration Files}}}
Like Grub Legacy grub2 resides in /boot/grub but there is ''no menu.lst'' file in Grub2. Its configuration file is ''/boot/grub/grub.cfg''. But be careful, this file is not meant to be manually edited (read the last part of this article if you want to edit it anyway). Don't worry, that doesn't mean that you can't configure grub2. Actually, grub.cfg is generated by individual scripts residing in ''/etc/grub.d/'' when ''update-grub command'' is executed and only read permissions are given to this file to avoid manual editing.

@@color:red;''[註] /boot/grub/grub.cfg 是 /etc/grub.d/ 目錄中所有 script 及 /etc/default/grub 設定值的執行結果''@@

This file grub.cfg is divided into sections, each section is handled by an individual script file (in ''/etc/grub.d'' folder). You may see entries similar to the following in your grub.cfg file. (/etc/grub.d 目錄中的程式, 會被 update-grub 命令執行)
{{{
### BEGIN /etc/grub.d/10_linux ###
set root=(hd0,5)
search --fs-uuid --set b02e1934-12dd-418a-be3a-9ff7d3e7e7ea
menuentry "Ubuntu, linux 2.6.28-13-generic" {
       linux   /boot/vmlinuz-2.6.28-13-generic root=UUID=b02e1934-12dd-418a ro  quiet splash vga800
       initrd  /boot/initrd.img-2.6.28-13-generic
}
### END /etc/grub.d/10_linux ###
}}}
These lines mean that this section is handled by the script file ''/etc/grub.d/10_linux''. There are similar sections for each script file. Their naming scheme is similar too (XX_filename, XX is the 2 digit number e.g 10, 20). These special names decide which script to run first. The file that comes before another in the alphabetical ordering will be executed first (e.g. 10_hurd will be executed before 10_linux which will be execute before 20_memtest86).

There is another important file responsible for the content of grub.cfg, it is ''/etc/default/grub''. This file holds the content previously found in the upper section of menu.lst. These settings are primarily concerned with Grub's menu display. So, if you want to change any setting related to the grub display or interface then change this file. And ''yes, this file can be manually configured''.

''[註] /etc/default/grub 這檔案, 主要功能是 Grub's menu display''

<<toBalaNotes "grub2">>
{{item1{顯示開機選單}}}
''1. 修改 /etc/default/grub''
$ sudo nano /etc/default/grub
{{{
# If you change this file, run 'update-grub' afterwards to update
# /boot/grub/grub.cfg.

GRUB_DEFAULT=0
#GRUB_HIDDEN_TIMEOUT=12                                    // 這行註解
#GRUB_HIDDEN_TIMEOUT_QUIET=false                      // 這行註解
GRUB_TIMEOUT=10                                           // 將 10 改成 20
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
GRUB_CMDLINE_LINUX=""
                         :
}}}

''2. 執行 sudo update-grub2''

$ sudo update-grub2
{{{
Generating grub.cfg ...
Found linux image: /boot/vmlinuz-2.6.31-14-generic-pae
Found initrd image: /boot/initrd.img-2.6.31-14-generic-pae
Found memtest86+ image: /boot/memtest86+.bin
done
}}}

''3. 重新開機''
{{{
$ sudo reboot
}}}

''4. 出現選單''

[img[img/linux/grub2menu.png]]

<<toBalaNotes "menu">>

{{item1{練習 : 設定開機選單的背景圖}}}

請參考 [[修改 Ubuntu 9.10 的 GRUB 2 開機畫面|http://superstanwu.blog.ithome.com.tw/post/775/67160]] 這篇文章




///%grub2
//%/

///%menu
//%/
''參考文章''
1. Learn Linux, 101: Hard disk layout
http://www.ibm.com/developerworks/linux/library/l-lpic1-v3-102-1/
2. Understanding UNIX / Linux filesystem Superblock
http://www.cyberciti.biz/tips/understanding-unixlinux-filesystem-superblock.html
3. Find and place system files
http://www.ibm.com/developerworks/linux/library/l-lpic1-v3-104-7/index.html

{{item1{Linux 檔案系統}}}
A Linux filesystem contains files that are arranged on a disk or other block storage device in directories. As with many other systems, directories on a Linux system may contain other directories called subdirectories. Unlike a system such as Microsoft® Windows® with a concept of separate file systems on different drive letters (A:, C:, etc.), a Linux filesystem is a single tree with the ''/'' directory as its ''root directory''.

You might wonder why disk layout is important if the filesystem is just ''one big tree''. Well, what really happens is that each block device, such as a hard drive partition, CD-ROM, or floppy disk, actually has a filesystem on it. You create the single tree view of the filesystem by mounting the filesystems on different devices at a point in the tree called a ''mount point''.

''[註]''  Linux 檔案系統是一棵大樹, 上面可掛載不同儲存裝置 (CD-ROM, 硬碟分割區, ...) 

Usually, the kernel starts this mount process by mounting the filesystem on some hard drive partition as /. You may mount other hard drive partitions as /boot, /tmp, or /home. You may mount the filesystem on a floppy drive as /mnt/floppy, and the filesystem on a CD-ROM as /media/cdrom1, for example. You may also mount files from other systems using a networked filesystem such as NFS. There are other types of file mounts, but this gives you an idea of the process. While the mount process actually mounts the filesystem on some device, it is common to simply say that you "mount the device," which is understood to mean "mount the filesystem on the device."

''[註]'' 系統一啟動, 會先建立 "/", "/boot", "/tmp" 等系統核心目錄 (放在 RAM Disk), 然後再把其他裝置掛載進來

Now, suppose you have just mounted the root file system (/) and you want to mount a CD-ROM, /dev/sr0, at the mount point /media/cdrom. The mount point must exist before you mount the CD-ROM over it. When you mount the CD-ROM, the files and subdirectories on the CD-ROM become the files and subdirectories in and below /media/cdrom. Any files or subdirectories that were already in /media/cdrom are no longer visible, although they still exist on the block device that contained the mount point /media/cdrom. If the CD-ROM is unmounted, then the original files and subdirectories become visible again. You should avoid this problem by not placing other files in a directory intended for use as a mount point. 

''[註]'' 儲存裝置在掛載之前, 必須先產生一個掛載點 (mount point), 才可掛載到此掛載點, 至於此儲存裝置中的檔案系統, 可以有許多不同格式 (Ext2, Ext3, Ext4, FAT, FAT32,....)

''Ext2'' is an older Linux file system. It's still often used on flash drives, because it doesn't write to the drive that often, and flash drives can be written to only a limited number of times before wearing out. But other than that, Ext2 was largely superseded by ''Ext3'', which added journaling to Ext2. Journaling file systems keep a record, or journal, of changes to the main file system. With journaling, if the file system crashes, it's much easier to restore it to a working condition without losing any data.

The newest member of the Ext file system, ''Ext4'', became an official part of Linux last year with the release of the Linux 2.6.28 kernel. Since then, it's become the default file system in some popular Linux distributions such as Fedora, and it's now available on all distributions.

''Ext4 enables faster disk performance and better drive space management than its predecessors''. While it also includes journaling, you can turn that off for a modest speed boost. I'm sure Google was also interested in it because even without disabling journaling, Ext4 is a very fast file system, and it supports file systems of up to ''1 EB (exabyte)'' and up to ''16 TB (terabyte)-sized files''. 

{{item1{Ubuntu 10.04 提供的檔案系統命令}}}
{{{
$ ls -al /sbin/mkfs.*
-rwxr-xr-x 1 root root 13824 2010-03-23 01:51 /sbin/mkfs.bfs
-rwxr-xr-x 1 root root 22036 2010-03-23 01:51 /sbin/mkfs.cramfs
-rwxr-xr-x 1 root root 55176 2010-04-19 12:30 /sbin/mkfs.ext2
-rwxr-xr-x 1 root root 55176 2010-04-19 12:30 /sbin/mkfs.ext3
-rwxr-xr-x 1 root root 55176 2010-04-19 12:30 /sbin/mkfs.ext4
-rwxr-xr-x 1 root root 55176 2010-04-19 12:30 /sbin/mkfs.ext4dev
-rwxr-xr-x 1 root root 19060 2010-03-23 01:51 /sbin/mkfs.minix
lrwxrwxrwx 1 root root     7 2010-05-03 16:15 /sbin/mkfs.msdos -> mkdosfs
lrwxrwxrwx 1 root root    16 2010-05-03 16:15 /sbin/mkfs.ntfs -> /usr/sbin/mkntfs
lrwxrwxrwx 1 root root     7 2010-05-03 16:15 /sbin/mkfs.vfat -> mkdosfs
}}}

<<toBalaNotes "fsys">>
{{item1{Filesystem Hierarchy Standard (FHS : 標準目錄架構)}}}
FHS 維基百科 : http://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard

The Filesystem Hierarchy Standard (FHS) defines the main directories and their contents in Linux operating systems. For the most part, it is a formalization and extension of the traditional BSD  filesystem hierarchy.

The FHS is maintained by the [[Free Standards Group|http://en.wikipedia.org/wiki/Free_Standards_Group]], now the [[Linux Foundation|http://en.wikipedia.org/wiki/Linux_Foundation]], a non-profit organization consisting of major software and hardware vendors, such as HP, Red Hat, IBM and Dell.

The current version is 2.3, announced on 29 January 2004.

[img[img/FS-layout.png]]

|''Directory''|''Description''|
|''/''|Primary hierarchy root and root directory of the entire file system hierarchy.|
|''/bin/''|Essential command binaries that need to be available in single user mode; for all users, e.g., cat, ls, cp.|
|''/boot/''|Boot loader files, e.g., kernels, initrd; often a separate partition|
|''/dev/''|Essential devices, e.g., /dev/null.|
|''/etc/''|Host-specific system-wide configuration files (the name comes from et cetera).|
|''/home/''|Users' home directories, containing saved files, personal settings, etc.; normally a separate partition.|
|/lib/|Libraries essential for the binaries in /bin/ and /sbin/.|
|/media/|Mount points for removable media such as CD-ROMs (appeared in FHS-2.3).|
|/mnt/|Temporarily mounted filesystems.|
|/opt/|Optional application software packages.|
|/proc/|Virtual filesystem documenting kernel and process status as text files, e.g., uptime, network. In Linux, corresponds to a Procfs mount.|
|''/root/''|Home directory for the root user.|
|/sbin/|Essential system binaries, e.g., init, ip, mount.|
|/srv/|Site-specific data which is served by the system.|
|/tmp/|Temporary files (see also /var/tmp). Often not preserved between system reboots.|
|/usr/|Secondary hierarchy for read-only user data; contains the majority of (multi-)user utilities and applications.|
|/var/|Variable files—files whose content is expected to continually change during normal operation of the system—such as logs, spool files, and temporary e-mail files. Sometimes a separate partition.|

{{item1{The two independent FHS categories}}}
本文網址 : http://www.ibm.com/developerworks/linux/library/l-lpic1-v3-104-7/index.html

At the core of the FHS are two independent characteristics of files:

''1. Shareable vs. unshareable''
Shareable files can be located on one system and used on another, while unshareable files must reside on the system on which they are used.

''2. Static vs. variable''
Static files change only through system administrator intervention, such as installing or upgrading a package, and include documentation, libraries, and binaries. Variable files are all other files, such as logs, spool files, databases, and user data, which are subject to change by users and by system processes.

These distinctions allow files with different sets of characteristics to be stored on different filesystems. Table 1 is an example from the FHS document showing a layout that would be FHS compliant.

 Table 1. FHS example  	
||''Shareable''|''Unshareable''|
|Static|/usr, /opt|/etc, /boot|
|Variable|/var/mail,/var/spool/news|/var/run,/var/lock|
<<toBalaNotes "fs">>

///%fs
//%/

///%fsys
//%/
{{item1{第一階段 : 取出 Gateway IP 位址}}}
{{{
$ cat /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet static
  address 192.168.56.5
  netmask 255.255.255.0
  gateway 192.168.56.2

$ grep gateway /etc/network/interfaces
  gateway 192.168.56.2

$ g=$(grep gateway /etc/network/interfaces)

$ echo ${g##* }
192.168.56.2
}}}

<<toBalaNotes "1">>
{{item1{第二階段 : 撰寫顯示 Gateway IP 位址程式}}}
{{{
$ nano chggw.sh
#!/bin/bash

[ "$USER" != "root" ] && echo "need root" && exit 1

g=$(grep gateway /etc/network/interfaces)
gw=${g##* }

if [ -n "$gw" ]; then
   echo "Gateway : $gw"
fi

exit 0
}}}


{{item1{第三階段 : 撰寫修改 Gateway IP 位址程式}}}
{{{
$ nano chggw.sh
#!/bin/bash

[ "$USER" != "root" ] && echo "need root" && exit 1

g=$(grep gateway /etc/network/interfaces)
gw=${g##* }

if [ -n "$gw" ]; then
   echo "Gateway : $gw"
   read -p "change gateway (y/n) " ans
   if [ "$ans" == "y" ]; then
      read -p "New Gateway Address : " ngw
      cat /etc/network/interfaces | sed "s/$gw/$ngw/" &> /tmp/chggw.tmp
      [ "$?" == 0 ] && cp /tmp/chggw.tmp /etc/network/interfaces && echo "ok"
   fi
fi

exit 0
}}}

<<toBalaNotes "2">>



///%1
//%/

///%2
//%/
''參考文章''
1. Learn Linux, 101: The Linux command line
http://www.ibm.com/developerworks/linux/library/l-lpic1-v3-103-1/index.html

When you are running in a bash shell, many things constitute your environment, such as the form of your prompt, your home directory, your working directory, the name of your shell, files that you have opened, functions that you have defined, and so on. Your environment includes many variables that may have been set by bash or by you. The bash shell also allows you to have shell variables, which you may export to your environment for use by other processes running in the shell or by other shells that you may spawn from the current shell.

{{item1{Bash 內建環境變數}}}
|''Name''|''Function''|
|USER|The name of the logged-in user|
|UID|The numeric user id of the logged-in user|
|HOME|The user's home directory|
|PWD|The current working directory|
|SHELL|The name of the shell|
|$|The process id (or PIDof the running bash shell (or other) process|
|PPID|The process id of the process that started this process (that is, the id of the parent process)|
|?|The exit code of the last command|

''顯示 Bash 內建環境變數內容''
Both environment variables and shell variables have a name. You reference the value of a variable by prefixing its name with '$'. 
{{{
$ echo $USER $UID
ian 500
$ echo $SHELL $HOME $PWD
/bin/bash /home/ian /home/ian
$ (exit 0);echo $?;(exit 4);echo $?
0
4
}}}

''顯示所有 Bash 環境變數 - env 命令''
The ''env'' command without any options or parameters displays the current environment variables. You can also use it to execute a command in a custom environment. The ''-i (or just -)'' option clears the current environment before running the command, while the -u option unsets environment variables that you do not wish to pass.
{{{
$ env
HOSTNAME=echidna
SELINUX_ROLE_REQUESTED=
TERM=xterm
SHELL=/bin/bash
HISTSIZE=1000
SSH_CLIENT=9.27.206.68 1316 22
SELINUX_USE_CURRENT_RANGE=
QTDIR=/usr/lib/qt-3.3
QTINC=/usr/lib/qt-3.3/include
SSH_TTY=/dev/pts/3
USER=ian
...
_=/bin/env
OLDPWD=/etc

$ env -i bash -c 'echo $SHELL; env'
/bin/bash
PWD=/home/ian
SHLVL=1
_=/bin/env
}}}

Notice that bash has set the SHELL variable, but not exported it to the environment, although there are three other variables that bash has created in the environment. In the ksh example, we have two environment variables, but our attempt to echo the value of the SHELL variable gives a blank line. Finally, tcsh has not created any environment variables and produces an error at our attempt to reference the value of SHELL. 

{{item1{自定環境變數}}}
{{{
$ VAR1=var1
$ VAR2=var2
$ export VAR2
$ bash 
$ export VAR3=var3
$ echo $VAR1 $VAR2 $VAR3
var2 var3
$ exit
$ echo $VAR1 $VAR2 $VAR3
var1 var2
}}}

''Unset and set''
While this article focuses on bash, it is good to know that not all shells behave the same way. Furthermore, shells behave differently according to whether they are a login shell or not. For now, we will just say that a login shell is the shell you get when you log in to a system; you can start other shells to behave as login shells if you wish. The three shells started above using env -i were not login shells. Try passing the -l option to the shell command itself to see what differences you would get with a login shell.

So let's consider our attempt to display the SHELL variable's value in these non-login shells:
{{{
1. When bash started, it set the SHELL variable, but it did not automatically export it to the environment.
2. When ksh started, it did not set the SHELL variable. However, referencing an undefined environment variable is equivalent to referencing one with an empty value.
3. When tcsh started, it did not set the SHELL variable. In this case, the default behavior is different than ksh (and bash) in that an error is reported when we attempt to use a variable that does not exist.
}}}
You can use the unset command to unset a variable and remove it from the shell variable list. If the variable was exported to the environment, this will also remove it from the environment. You can use the set command to control many facets of the way bash (or other shells) work. Set is a shell builtin, so the various options are shell specific. In bash, the -u option causes bash to report an error with undefined variables rather than treat them as defined but empty. You can turn on the various options to set with a - and turn them off with a +. You can display currently set options using echo $-.
{{{
$ echo $-                                  # display currently set options
himBH
$ echo $VAR1

$ set -u;echo $-
himuBH
$ echo $VAR1
-bash: VAR1: unbound variable
$ VAR1=v1
$ VAR1=v1;echo $VAR1
v1
$ unset VAR1;echo $VAR1
-bash: VAR1: unbound variable
$ set +u;echo $VAR1;echo $-

himBH
}}}

If you use the set command without any options, it displays all your shell variables and their values (if any). There is also another command, declare, which you can use to create, export, and display values of shell variables. You can explore the many remaining set options and the declare command using the man pages. We will discuss man pages later in this article. 

{{item1{Bash 提示字串}}}
''檢視目前 Bash 提示字串格式''
{{{
# echo $PS1
\u@\h:\w\$

說明 :
“\u” : User Name (whoami)
“\h” : host name  (hostname)
“\w” : Current Directory (pwd)
}}}

''設定 Bash 提示字串格式''
{{{
# export PS1=“[\u@\h] “
}}}

<<toBalaNotes "bashpromp">>

///%bashpromp
//%/

{{item1{方法一}}}

''1. Run the command "sudo gedit /etc/init/rc-sysinit.conf"''

[img[img/ubuntu10.4/Desktop/ud2text01.png]]

''2. sudo gedit /etc/init/gdm.conf''

[img[img/ubuntu10.4/Desktop/ud2text02.png]]

<<toBalaNotes "1">>

{{item1{方法二}}}
Another way of changing to text mode is to pass the argument "text" to the kernel while booting.
we can do this as follows

1. While the sytem boots hold the "shift" key so that the gurb menu gets displayed
2. Move to the line that has the kernel you boot, some thing like

Ubuntu, with Linux 2.6.32-28-generic

3. Press "e"
4. Move to the line that starts with "linux"
5. Press e again to edit and at the end of this line add the word "text" and press enter.
6. Press cntrl+x to boot the system in text mode.

You can also add a permanent option in your grub menu for the text mode which can be done as follows.
1. Open the file /boot/grub/grub.cfg  using "sudo gedit /boot/grub/grug.cfg"
2. Go to the section that starts with "BEGIN /etc/grub.d/10_linux"
3. Copy the menuentry of the kernel you want to boot in text mode.
4. Open the file /etc/grub.d/40_custom using "sudo gedit /etc/grub/40_custom"
5. Paste the entry copied from grub.cfg at the end of this file.
6. In menuentry add the string "text" at the end of the line that starts with "linux" and save the file
7. Run the command "sudo update-grub2"
8. Now restart the system and hold shift to see the grub menu.
9. You should see a new entry at the end, which if selected should boot into the text mode.
<<toBalaNotes "2">>


///%1
//%/

///%2
//%/

{{item1{在 Ubuntu 10.04 桌面版, 安裝 vmware-tools}}}
如果你使用 VMware Workstation 7 或者 VMware Server 2,這兩者內附的 vmware-tools 都還不支援 Ubuntu 10.04 LTS 所使用的2.6.32 版核心,你必須改用 open-vm-tools。

安裝 open-vm-tools 時,最好自行選擇要安裝的核心標頭檔案。像我安裝時選擇 Ubuntu Server 最小虛擬機器安裝,被安裝的核心應該是 linux-virtual,但是安裝進去的卻是 linux-generic-pae,安裝 open- vm-tools 時,套件管理程式會自動選擇不同的核心標頭檔案,導致核心模組編譯失敗。

''安裝 核心標頭檔案''
{{{
$ sudo apt-get install linux-headers-$(uname -r)
}}}

透過 aptitude 安裝,應該選取以下套件:

* linux-headers-$(uname -r) (根據你的系統來選擇標頭檔)
* open-vm-dkms
* open-vm-source
* open-vm-toolbox (選用,如果你有安裝桌面環境)
* open-vm-tools

{{item1{在 Ubuntu Server 安裝 VMware-tools}}}
在 VMware 的虛擬主機中, 要提升 Ubuntu JeOS 的執行效能, 那就必須在 Ubuntu JeOS 系統中, 安裝 VMware Tools. 以下的實作範例, 是在 VMware Workstation 6.5.2 執行 Ubuntu 9.04 系統中完成.

{{item1{安裝前準備}}}

''1. 安裝編譯所需程式 (gcc, make,..)''
{{{
# sudo apt-get install build-essential linux-headers-$(uname -r)
}}}
    
''2. 將 C:\Program Files\VMware\VMware Workstation 目錄中的 linux.iso, 掛載到此虛擬主機的 CD/DVD (IDE) 裝置, 如下圖 :''

[img[img/vmware/vmtoolsins01.png]]

''3. 掛載光碟''
{{{
$ mkdir cdrom
$ sudo mount  /dev/cdrom  cdrom
}}}

''4. 解壓縮 VMware Tools 安裝程式''
{{{
$ mkdir vmtools
$ cd vmtools
$ tar xvfz ../cdrom/VMwareTools-8.4.2-261024.tar.gz
}}}

{{item1{開使安裝}}}
這階段會詢問你, 要安裝那些 VMware Tools 功能, 例如 vmxnet, vmmemctl, vmblock 等. 因 VMware Server 及 VMware Player 並沒提供 Share Folders(vmhgfs) 功能, 所以安裝過程中, 請回答不要安裝 vmhgfs, 安裝命令如下 :

''$ cd vmware-tools-distrib/''
''$ sudo ./vmware-install.pl''
{{{
Creating a new VMware Tools installer database using the tar4 format.

Installing VMware Tools.

In which directory do you want to install the binary files?
[/usr/bin]

What is the directory that contains the init directories (rc0.d/ to rc6.d/)?
[/etc]

What is the directory that contains the init scripts?
[/etc/init.d]

In which directory do you want to install the daemon files?
[/usr/sbin]

In which directory do you want to install the library files?
[/usr/lib/vmware-tools]

The path "/usr/lib/vmware-tools" does not exist currently. This program is
going to create it, including needed parent directories. Is this what you want?
[yes]

In which directory do you want to install the documentation files?
[/usr/share/doc/vmware-tools]

The path "/usr/share/doc/vmware-tools" does not exist currently. This program
is going to create it, including needed parent directories. Is this what you
want? [yes]

The installation of VMware Tools 7.8.4 build-126130 for Linux completed
successfully. You can decide to remove this software from your system at any
time by invoking the following command: "/usr/bin/vmware-uninstall-tools.pl".

Before running VMware Tools for the first time, you need to configure it by
invoking the following command: "/usr/bin/vmware-config-tools.pl". Do you want
this program to invoke the command for you now? [yes]


Stopping VMware Tools services in the virtual machine:
Guest operating system daemon: done
Virtual Printing daemon: done
None of the pre-built ''vmmemctl modules'' for VMware Tools is suitable for your
running kernel. Do you want this program to try to build the vmmemctl module
for your system (you need to have a C compiler installed on your system)?
[yes] ''Enter''
:
The vmmemctl module loads perfectly into the running kernel.

None of the ''pre-built vmhgfs modules'' for VMware Tools is suitable for your
running kernel. Do you want this program to try to build the vmhgfs module for
your system (you need to have a C compiler installed on your system)? [yes] ''no''

The filesystem driver (vmhgfs module) is used only for the shared folder
feature. The rest of the software provided by VMware Tools is designed to work
independently of this feature.

If you wish to have the shared folders feature, you can install the driver by
running vmware-config-tools.pl again after making sure that gcc, binutils, make
and the kernel sources for your running kernel are installed on your machine.
These packages are available on your distribution's installation CD.
[ Press Enter key to continue ]

None of the ''pre-built vmxnet'' modules for VMware Tools is suitable for your
running kernel. Do you want this program to try to build the vmxnet module for
your system (you need to have a C compiler installed on your system)? [yes] ''Enter''

:
The vmxnet module loads perfectly into the running kernel.

update-initramfs: Generating /boot/initrd.img-2.6.27-7-server
None of the pre-built vmblock modules for VMware Tools is suitable for your
running kernel. Do you want this program to try to build the vmblock module
for your system (you need to have a C compiler installed on your system)?
[yes]
:
The vmblock module loads perfectly into the running kernel.

[EXPERIMENTAL] The ''VMware FileSystem Sync Driver (vmsync)'' is a new feature that
creates backups of virtual machines. Please refer to the VMware Knowledge Base
for more details on this capability. Do you wish to enable this feature?
[no]

None of the ''pre-built vmci modules'' for VMware Tools is suitable for your
running kernel. Do you want this program to try to build the vmci module for
your system (you need to have a C compiler installed on your system)? [yes] ''Enter''

:
The vmci module loads perfectly into the running kernel.

None of the ''pre-built vsock modules'' for VMware Tools is suitable for your
running kernel. Do you want this program to try to build the vsock module for
your system (you need to have a C compiler installed on your system)? [yes] ''Enter''
:
The VM communication interface socket family is used in conjunction with the VM
communication interface to provide a new communication path among guests and
host. The rest of this software provided by VMware Tools is designed to work
independently of this feature. If you wish to have the VSOCK feature you can
install the driver by running vmware-config-tools.pl again after making sure
that gcc, binutils, make and the kernel sources for your running kernel are
installed on your machine. These packages are available on your distribution's
installation CD.
[ Press the Enter key to continue.]

No X install found.

Checking acpi hot plug done
Starting VMware Tools services in the virtual machine:
Switching to guest configuration: done
Guest memory manager: done
Guest vmxnet fast network device: done
VM communication interface: done
Blocking file system: done
Guest operating system daemon: done
Virtual Printing daemon: done

The configuration of VMware Tools 7.8.4 build-126130 for Linux for this running
kernel completed successfully.

You must restart your X session before any mouse or graphics changes take
effect.

You can now run VMware Tools by invoking the following command:
"/usr/bin/vmware-toolbox" during an X server session.

To enable advanced X features (e.g., guest resolution fit, drag and drop, and
file and text copy/paste), you will need to do one (or more) of the following:
1. Manually start /usr/bin/vmware-user
2. Log out and log back into your desktop session; and,
3. Restart your X session.

To use the vmxnet driver, restart networking using the following commands:
/etc/init.d/networking stop
rmmod pcnet32
rmmod vmxnet
modprobe vmxnet
/etc/init.d/networking start

Enjoy,

-the VMware team
}}}

{{item1{安裝高速網卡}}}
安裝 vmxnet 網卡驅動程式, 使網卡速度在虛擬網路中可達 1G, 安裝命令如下 :
{{{
# sudo /etc/init.d/networking stop
# sudo rmmod pcnet32
# sudo rmmod vmxnet
# sudo modprobe vmxnet
# sudo /etc/init.d/networking start
}}}
''[注意]'' 請勿使用 ssh 終端機程式, 執行上述命令, 因網路會中斷

{{item1{修改 99-vmware-scsi-udev.rules 執行檔}}}
不修改此檔, 開機時會出現以下錯誤訊息 
{{{
udevd[324]: BUS= will be removed in a future udev version, please use SUBSYSTEM= to match the event device, or SUBSYSTEMS= to match a parent device, in /etc/udev/rules.d/99-vmware-scsi-udev.rules:12
}}}

''$ sudo nano /etc/udev/rules.d/99-vmware-scsi-udev.rules''
{{{
#
# VMware SCSI devices Timeout adjustment
#
# Modify the timeout value for VMware SCSI devices so that
# in the event of a failover, we don't time out.
# See Bug 271286 for more information.
#
# Note: The Udev systems vary from distro to distro.  Hence all of the
#       extra entries.

# Redhat systems
#ACTION=="add", BUS=="scsi", SYSFS{vendor}=="VMware, " , SYSFS{model}=="VMware $     // 註解此行

# Debian systems
#ACTION=="add", SUBSYSTEMS=="scsi", ATTRS{vendor}=="VMware  " , ATTRS{model}=="$   // 註解此行

# SuSE / Ubuntu systems
ACTION=="add", SUBSYSTEMS=="scsi", ATTRS{vendor}=="VMware, " , ATTRS{model}=="V$
}}}


{{item1{重新開機}}}
執行 sudo reboot 命令, 重新啟動系統, 如安裝順利, 啟動後畫面如下 :

[img[img/vmware/vmtoolsins02.png]]

<<toBalaNotes "vmtools">>






///%vmtools
//%/
1.啟動 WinSCP

2. 輸入登入資訊

[img[img/winscp/winscp01.png]]

3.點選 ''環境'', 然後點選旁邊的 ''UTF-8 檔案名稱編碼 (U)'',  選擇 "開啟"

[img[img/winscp/winscp02.png]]

4. 儲存設定

[img[img/winscp/winscp03.png]]

5. 登入系統

[img[img/winscp/winscp04.png]]

[img[img/winscp/winscp05.png]]

6. 檔案處理

[img[img/winscp/winscp06.png]]

<<toBalaNotes "scp">>


///%scp
//%/
{{item1{參數檢查}}}
''$ nano param01.sh''
{{{
if [ "$#" == "0" ] then
   echo "No Good"
fi
}}}

''$ bash param01.sh''
{{{
param01.sh: line 3: syntax error near unexpected token `fi'
param01.sh: line 3: `fi'
}}}

''[問題]'' 上面範例程式, 為何執行錯誤 ?

''$ nano check.sh''
{{{
#!/bin/bash
# 下式的另一種語法 if (test "$1" = "start") then
if [ "$1" == "start" ]; then
   echo "Network Up"
else
   echo "Network Down"
fi

$ chmod  +x  chech.sh
}}}

{{item1{字串判斷}}}
''$ nano  mytar.sh''
{{{
#!/bin/bash

if  [  “${1##*.}” = “tar”  ]                         # 單一 "=" 一樣可以執行等於判斷
then
       echo This appears to be a tarball.
else
       echo At first glance, this does not appear to be a tarball.
fi
}}}

''$  chmod  +x  mytar.sh''

''$  ./mytar.sh  thisfile.tar''
{{{
This appears to be a tarball.
}}}

''$ nano  myvar.sh''
{{{
mv=“foo bar oni”

if [  -z  "$mv"  ]
then
   echo  “mv is not defined”
fi

if [  "$mv" = “foo bar oni”  ]                # 單一 "=" 一樣可以執行等於判斷
then
   echo "yes"
fi
}}}

''$  chmod  +x  myvar.sh''

''$  ./myvar.sh''
<<toBalaNotes "if">>
{{{
#!/bin/bash

type unzip &>/dev/null
if [ "$?" != "0" ]; then
    sudo apt-get install unzip &>/dev/null
fi

if [ -z "$SSH_TTY" ]; then
   export LANG='en_US.UTF-8'
   export LANGUAGE='en_US'
else
   h=$(echo $SSH_CLIENT | cut -d' ' -f1)
   grep "$h$" "./iplist.txt" &>/dev/null
   if [ "$?" == "0" ]; then
      exit 1
   fi
fi
}}}



///%if
//%/

<<forEachTiddler 
 where
   'tiddler.tags.contains("plugin")'
>>
{{item1{安裝 tree 套件}}}
{{{
$ sudo apt-get install tree
}}}

{{item1{移除 tree 套件}}}
{{{
$ sudo apt-get remove tree
}}}

<<toBalaNotes "tree">>
{{item1{apt-get 指令操作}}}
apt-get 是每個 Debian 使用者常會用到的指令,它是軟體 dpkg 的前端程式,因為 dpkg 的指令參數實在太多了,所以才會有這套程式的產生。『 apt-get 』指令操作非常簡單,底下列出比較常用的選項及參數,要得到最完整的資訊請 『 man apt-get 』。

''[注意]'' 執行 『 apt-get 』 指令時需以 『 root 』 身份執行 !

''apt-get update''
軟體資料庫同步:apt-get update 會根據 /etc/apt/sources.list 中設定到 APT Server 去更新軟體資料庫,在任何更新之前最好都先做這一個動作,讓軟體資料保持在最新的狀況之下。/etc/apt/sources.list 可以用 apt-setup 來設定。

''apt-get install package_nam''
軟體安裝:安裝軟體最怕的就是軟體間的相依、相斥關係,但是在 Debian 裡頭安裝軟體是一件非常愉悅的事情,只要 『 apt-get install 』一行指令簡簡單單輕輕鬆鬆即可完成,所有相依、相斥 Debian 都會幫我們自動解決,您只要回答 『 Y 』就可以。

''apt-get remove package_nam''
軟體移除:與 install 一樣,Debian 一樣會幫您處理移除軟體時所發生的相依問題。

''apt-get purge package_nam''
軟體移除:與 remove 相同,但連設定檔也會移除。

''apt-get upgrade''
軟體升級:平常我們很難顧慮到系統上所安裝的數十甚至數百套軟體的版本是否有新版出現,現在只要下這個指令 Debian 便會自動找出所有有新版的軟體套件並逐一升級。

''apt-get dist-upgrade''
系統升級:當轉移整個系統時,如 『 stable 』 轉換到 『 testing 』,或是系統運行好一段時間都應該下這個指令,它會聰明的處理到很多軟體相依、相斥的問題。

''apt-get source''
如果您想取得某個軟體套件 ( packages ) 的原始碼可以透過這個指令達成。

''apt-get clean''
我們透過 apt-get 安裝的任何軟體都會先下載到 『 /var/cache/apt/archives/ 』及 『 /var/cache/apt/archive/partial/ 』 目錄底下,一般預設 apt-get 在安裝完軟體後是不會把上述位置底下的 『 .deb 』 殺除,一段時間後您如果覺得系統空間不足,您可以下 『 apt-get clean 』讓系統自動清理這個目錄。

''apt-get autoclean''
類似 『 apt-get clean 』,下此參數時 apt-get 在安裝完畢後會自動刪除該軟體的 『 .deb 』 檔。

''apt-get check''
apt-get 不是萬能,有時候也是會出現問題,遇到有問題的時候您可以下 『 apt-get check 』來診斷問題所在。
如果出現下面的畫面代表存有相依性的問題
{{{
Reading Package Lists... Done
Building Dependency Tree... Done
You might want to run `apt-get -f install' to correct these.
The following packages have unmet dependencies:
  php: Depends: libiconv.so.2 but it is not installable
E: Unmet dependencies. Try using -f.
}}}
如果系統沒問題,則是下列的畫面
{{{
Reading Package Lists... Done
Building Dependency Tree... Done
}}}

''apt-get purge `deborphan`'' ( 清除系統多餘的 library )

{{{
* apt-get update:在修改 /etc/apt/sources.list 或 /etc/apt/preferences 之後要執行這道指令。此外,也需要定期執行以確保系統的資列表是最新的。
* apt-get install packagename:安裝新套件
* apt-get remove packagename:移除已安裝的套件(設定檔會留著)
* apt-get --purge remove packagename:移除已安裝的套件(設定檔同時也會被移除)

   - 小技巧:若要用一道指令移除套件 foo 並安裝套件 bar;可以下這道指令:apt-get --purge remove foo bar+ 

* apt-get autoremove packagename:移除已安裝的套件以及其相依的套件
* apt-get upgrade:更新所有已安裝的套件
* apt-get dist-upgrade:更新整個系統至更新的版本,即使必須移除一些套件(較不推薦)
* apt-get -f install:若發生套件相依性的問題,用此指令來修復
* apt-get autoclean:定期執行來清理系統中不再被使用到的套件的 .deb檔。如此可以取得更多的磁碟空間。若需要更多的磁碟空間,可利用指令 apt-get clean 來清理所有 .deb 檔。

* apt-get clean:和上面的指令一樣,除了沒有移除所有 package cache 中的套件。o
* apt-cache search foo:尋找套件 foo
* apt-cache show foo:顯示出套件 foo 的相關資訊
* dpkg -l ’*foo*‘:找出名稱包含 foo 的套件
* dpkg -L foo:顯示出套件 foo 安裝於系統的檔案(此指令非常很有用)
* dlocate foo:顯示出名稱符合 foo 的套件的檔案,即哪些檔案是屬於套件 foo。此指令需要安裝 dlocate
* dpkg -S foo:與上面的指令一樣,但執行速度較慢,不需要安裝 dlocate
* apt-file search foo:和 dlocate 與 dpkg -S類似,但是尋找所有可得的套件,而不是只有已經安裝在你系統上的
* dpkg -c foo.deb:套件 foo.deb 包含什麼檔案? foo.deb 是路徑名稱,你已經下載放置好的位置
* dpkg-reconfigure foo:再次設定套件 foo
* apt-cache search string:搜尋已知套件列表 - Searches for string in the list of known packages
* dpkg -l package-name-pattern:列出已安裝且符合的套件
* aptitude - Curses viewer of packages installed or available. Aptitude can be used from the command-line in a similar way to apt-get, but only for some commands - install and remove being the most common. However, because aptitude keeps track of more information than apt-get does, it can be considered better at install and remove operations.

* apt-cache showpkg pkgs:顯示出套件的資訊 - Show information about packages.
* apt-cache dumpavail:印出可得的套件列表
* apt-cache show pkgs:顯示出套件紀錄,類似 dpkg --print-avail
* apt-cache pkgnames:快速列出系統中所有的套件
* dpkg -S file:哪一個已安裝的套件擁有此檔案?
* dpkg -L package:列出套件中的檔案
* apt-file search filename:搜尋包含 filename 的套件(尚未安裝過的)。apt-file 套件是獨立成套的,你必須要先安裝,再執行 apt-file update。若此指令顯示出太多資訊,可嘗試 apt-file search filename | grep -w filename 來顯示出包含整個檔案名稱的搜尋;或是利用 apt-file search filename | grep /bin/ 只搜尋目錄 /bin 或 /usr/bin 的結果

* echo "foo hold" | dpkg --set-selectons:將此套件鎖住,不允許升級
* echo "foo install":移除上述指令所設定的套件鎖定 
}}}


///%tree
//%/
<<forEachTiddler 
 where
 'tiddler.tags.length == 0'
>>
''[注意] 如要重新出題, 請關閉本篇文章, 然後再開啟''

<<toBalaTest "小考 (20 題)" "第一次模考" "2010_A01" "20" "950" "500" "100%" "100%">>

<<toBalaTest "期中考 (40 題)" "第二次模考" "2010_A01" "40" "950" "500" "100%" "100%">>

<<toBalaTest "期末考" "第三次模考" "2010_A01" "40" "950" "500" "100%" "100%">>

///%2010_A01
[
   ['img/lpic101/1.png', 'ABC'],
   ['img/lpic101/2.png', 'A'],
   ['img/lpic101/3.png', 'B'],
   ['img/lpic101/4.png', 'CD'],
   ['img/lpic101/5.png', 'ABD'],
   ['img/lpic101/6.png', 'ABC'],
   ['img/lpic101/7.png', 'A'],
   ['img/lpic101/8.png', 'B'],
   ['img/lpic101/9.png', 'CD'],
   ['img/lpic101/10.png', 'ABD'],
   ['img/lpic101/11.png', 'ABC'],
   ['img/lpic101/12.png', 'A'],
   ['img/lpic101/13.png', 'B'],
   ['img/lpic101/14.png', 'CD'],
   ['img/lpic101/15.png', 'ABD'],
   ['img/lpic101/16.png', 'ABC'],
   ['img/lpic101/17.png', 'A'],
   ['img/lpic101/18.png', 'B'],
   ['img/lpic101/19.png', 'CD'],
   ['img/lpic101/20.png', 'ABD'],
   ['img/lpic101/21.png', 'ABC'],
   ['img/lpic101/22.png', 'A'],
   ['img/lpic101/24.png', 'CD'],
   ['img/lpic101/25.png', 'ABD'],
   ['img/lpic101/26.png', 'ABC'],
   ['img/lpic101/30.png', 'ABD'],
   ['img/lpic101/31.png', 'ABC'],
   ['img/lpic101/32.png', 'A'],
   ['img/lpic101/33.png', 'B'],
   ['img/lpic101/34.png', 'CD'],
   ['img/lpic101/35.png', 'ABD'],
   ['img/lpic101/36.png', 'ABC'],
   ['img/lpic101/37.png', 'A'],
   ['img/lpic101/38.png', 'B'],
   ['img/lpic101/39.png', 'CD'],
   ['img/lpic101/40.png', 'ABD'],
   ['img/lpic101/41.png', 'A'],
   ['img/lpic101/42.png', 'B'],
   ['img/lpic101/43.png', 'CD'],
   ['img/lpic101/44.png', 'ABD'],
   ['img/lpic101/45.png', 'ABD'],
   ['img/lpic101/46.png', 'ABD'],
   ['', ''],   // 一定要加, 作為考題結束
]
//%/
{{item1{檢視權限刪減值}}}
{{{
# umask
0022                    (Ubuntu Server 的設定, 而 Trustix 內定為 0077)

# umask -S 
u=rwx,g=rx,o=rx
}}}
''[註]'' umask 是在 /etc/profile 中被設定
''[註]'' Shell 提示字元, 如有'#' , 代表 root, Shell 提示字元, 如有'$' , 代表一般使用者

{{item1{檔案的初設權限 (666)}}}
檔案預設權限是『沒有可執行( x )權限』,亦即只有 rw 這兩個項目,也就是最大為 666 分,預設權限如下:
{{{
-rw-rw-rw-
}}}
umask 的值指的是『該預設值需要減掉的權限!』因為 r、w、x 分別是 4、2、1 ,所以囉!也就是說,當要拿掉能寫的權限,就是輸入 2 

''檢視檔案權限''
{{{
$ touch  xyz    (建立新檔)

$ ls -al xyz
-rw-r--r-- 1 tobala tobala 0 2009-08-31 23:20 xyz

$ stat xyz
  File: 「xyz」
  Size: 0               Blocks: 0          IO Block: 4096   普通空白檔案
Device: 801h/2049d      Inode: 11014       Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/  tobala)   Gid: ( 1000/  tobala)
Access: 2009-08-31 23:20:41.000000000 +0800
Modify: 2009-08-31 23:20:41.000000000 +0800
Change: 2009-08-31 23:20:41.000000000 +0800
}}}

{{item1{目錄的初設權限}}}

''建立目錄 (目錄內定權限為 777)''
{{{
# mkdir  abc
}}}

''檢視目錄權限''
{{{
$ stat abc
  File: 「abc」
  Size: 4096            Blocks: 8          IO Block: 4096   目錄
Device: 801h/2049d      Inode: 11015       Links: 2
Access: (0755/drwxr-xr-x)  Uid: ( 1000/  tobala)   Gid: ( 1000/  tobala)
Access: 2009-08-31 23:23:33.000000000 +0800
Modify: 2009-08-31 23:23:33.000000000 +0800
Change: 2009-08-31 23:23:33.000000000 +0800
}}}

{{item1{自定權限遮置 (umask) 值}}}

''建立檔案''
{{{
# umask  0045
# touch  zzz
# stat  zzz
               :
Access: (0622/-rw--w-w-)   Uid:(1000/   profx)   Gid(1000/ profx)
}}}

''修改權限''
{{{
# chmod  +x  zzz               (修改後的權限, 還是會根 umask 作計算)
# stat  zzz                      
               :
Access: (0732/-rwx-wx-w-)   Uid:(1000/   profx)   Gid(1000/ profx)      (other 一樣沒有執行的權限)

# chmod  o+x  zzz             (這樣可以強迫修改 other 的 執行權限)
# stat  zzz
                     :
Access: (0733/-rwx-wx-wx)   Uid:(1000/   profx)   Gid(1000/ profx)

$ chmod 777 zzz                    (使用數字格式, 不受 umask 影響)
$ stat zzz
  File: 「zzz」
  Size: 0               Blocks: 0          IO Block: 4096   普通空白檔案
Device: 801h/2049d      Inode: 2691        Links: 1
Access: (0777/-rwxrwxrwx)  Uid: ( 1000/ student)   Gid: ( 1000/ student)
Access: 2010-09-22 23:57:41.072469195 +0800
Modify: 2010-09-22 23:57:41.072469195 +0800
Change: 2010-09-23 00:07:48.947976103 +0800
}}}

''練習 : 覆製檔案, 是否保留權限 ?''
{{{
# touch zzz
# stat zzz
# chmod 666 zzz
# cp  zzz   kkk                              #  因 kkk 這檔案是新產生, 所以會經過 umask 計算
# stat  kkk

# chmod 777 kkk                         
# cp zzz kkk
# stat kkk                                      # 因 kkk 這檔案已存在, 所以權限不會被改變 

# rm kkk
# cp -p zzz kkk                            # 不會經過 umask 計算, -p 代表保留權限
# stat kkk
}}}
<<toBalaNotes "1">>

///%1
//%/
''參考文章''
1. Find and place system files (必讀)
http://www.ibm.com/developerworks/linux/library/l-lpic1-v3-104-7/index.html

{{item1{locate 命令}}}
locate 尋找的資料是由『已建立的資料庫 /var/lib/mlocate/mlocate.db』 裡面的資料所搜尋到的,所以不用直接在去硬碟當中存取資料,更新 locate 資料庫的方法非常簡單,直接輸入『 updatedb 』就可以了! updatedb 指令會去讀取 /etc/updatedb.conf 這個設定檔的設定,然後再去硬碟裡面進行搜尋檔名的動作

''第一次操作''
{{{
$ ls -al /var/lib/mlocate/mlocate.db
-rw-r----- 1 root mlocate 1091375 2010-09-19 19:32 /var/lib/mlocate/mlocate.db       (Ubuntu 系統安裝後, mlocate.db 這資料庫已被建立)

$ locate ifconfig                               (使用 mlocate.db 資料庫, 可找到 ifconfig 命令)
/sbin/ifconfig
/usr/share/man/de/man8/ifconfig.8.gz
/usr/share/man/fr/man8/ifconfig.8.gz
/usr/share/man/man8/ifconfig.8.gz
/usr/share/man/pt_BR/man8/ifconfig.8.gz
}}}

''建立新檔''
{{{
$ touch abc.txt
$ locate abc.txt                     # 沒有找到檔案

$ updatedb                           
updatedb: can not open a temporary file for `/var/lib/mlocate/mlocate.db'
$ sudo updatedb                   # 更新資料庫

$ locate abc.txt
/home/cloudwalker/abc.txt
}}}

''updatedb 更新設定檔''
{{{
$ sudo nano /etc/updatedb.conf

PRUNE_BIND_MOUNTS="yes"
# PRUNENAMES=".git .bzr .hg .svn"
PRUNEPATHS="/tmp /var/spool /media"
PRUNEFS="NFS nfs nfs4 rpc_pipefs afs binfmt_misc proc smbfs autofs iso9660 ncpf$
}}}

''更新設定檔說明''
{{{
PRUNEFS
              A  whitespace-separated  list  of  file system types (as used in
              /etc/mtab) which should not be scanned by updatedb

PRUNEPATHS
              A whitespace-separated list of path names of  directories  which
              should  not  be  scanned by updatedb(8).  Each path name must be
              exactly in the form in which the directory would be reported  by
              locate.

PRUNE_BIND_MOUNTS
              One  of  the strings 0, no, 1 or yes.  If PRUNE_BIND_MOUNTS is 1
              or yes, bind mounts are not scanned by  updatedb(8).   All  file
              systems  mounted  in  the subtree of a bind mount are skipped as
              well, even if they are not bind mounts.

              By default, bind mounts are not skipped.
}}}

{{item1{whereis}}}
找尋 ''指定命令'' 的執行檔 (binary), 原始檔 (source) 及手冊檔 (manual page files), 此命令無法處理文字檔
{{{
#whereis bash
bash: /bin/bash  /usr/share/man/man1/bash.1.gz
}}}

{{item1{find  : 很操硬碟,速度慢 }}}
通常 ''find'' 不很常用的!因為速度慢之外, 也很操硬碟!通常我們都是先使用 whereis 或者是 locate 來檢查,如果真的找不到了,才以 find 來搜尋呦! 為什麼呢?因為 whereis 與 locate 是利用資料庫來搜尋資料,所以相當的快速,而且並沒有實際的搜尋硬碟, 比較省時間啦!
{{{
$ find  /usr  -name "*csh*"
/usr/share/vim/vim72/indent/tcsh.vim
/usr/share/vim/vim72/syntax/csh.vim
/usr/share/vim/vim72/syntax/tcsh.vim
/usr/share/vim/vim72/ftplugin/csh.vim
/usr/share/vim/vim72/ftplugin/tcsh.vim
/usr/share/doc/util-linux/examples/getopt-parse.tcsh
/usr/share/doc/util-linux/examples/getopt-test.tcsh

$ find / -maxdepth 1 -name b*   (只尋找 "/" 目錄內容, 不遞迴)
/boot
/bin

# find   /  -size  +500k        (遞迴處理, 尋找大於 500 K 的檔案)

# find  /root  ctime  1        (在 /root 目錄, 一天內有修改過的檔案)


$ find ~ -cmin -120    (120 分內有修改過的檔案)
/home/student
/home/student/abc.c
}}}

''find 參數''
{{{
-atime 檔案的最後存取時間到find 的執行時間差

-Btime 檔案的inode 建立時間到find 的執行時間差

-ctime 檔案的狀態資訊最後修改的時間到find 的執行時間差

-mtime 檔案的最後修改時間到 find 的執行時間差 (天 為單位)
}}}
<<toBalaNotes "fs">>

///%fs
//%/
''參考文章''
1. How to change message of the day (MOTD) in Ubuntu server
http://www.ubuntugeek.com/how-to-change-message-of-the-day-motd-in-ubuntu-server.html
2. Bash scripting for beginning system administrators
http://www.ibm.com/developerworks/aix/library/au-getstartedbash/index.html

{{item1{系統設定程式檔 (登入前會被執行)}}}

{{op1{1. /etc/rc.local}}}
''$ cat /etc/rc.local''
{{{
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

#/opt/lampp/lampp startapache

exit 0
}}}

{{op1{2. /etc/profile (針對所有登入者)}}}

''$ cat /etc/profile''
{{{
# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).

if [ -d /etc/profile.d ]; then
  for i in /etc/profile.d/*.sh; do
    if [ -r $i ]; then
      . $i
    fi
  done
  unset i
fi

if [ "$PS1" ]; then
  if [ "$BASH" ]; then
    PS1='\u@\h:\w\$ '
    if [ -f /etc/bash.bashrc ]; then
        . /etc/bash.bashrc
    fi
  else
    if [ "`id -u`" -eq 0 ]; then
      PS1='# '
    else
      PS1='$ '
    fi
  fi
fi

umask 022
}}}

{{op1{實作練習}}}
''在 Ubuntu Desktop 版中,  只要使用 xman01 這帳號登入, 桌面環境必須保持在最初狀態''

1. 建立 xman01 帳號
{{{
$ sudo useradd -m -s /bin/bash xman01
}}}

2. 使用 xman01 帳號登入

3. 登出, 然後使用初設帳號 (student) 登入

4. 修改 /etc/peofile 程式檔, 如下 :
{{{
                                  :
umask 022
rm -rf /home/xman01/* /home/xman01/.??*                     # 這行最前面不要加 sudo, 因系統執行 /etc/profile 是以 root 身份來執行
}}}

''[說明]''
rm -rf xman01/.??* 這命令主要是刪除隱藏檔, 因 ''.'' 及 ''..'' 不是隱藏檔, 要避開這二個檔案, 所以檔案格式為 ''.??*''

{{item1{個人設定程式檔}}}

{{op1{1. ~/.profile (登入後只會執行一次)}}}
這個設定程式檔, 會去執行 ~/.bashrc 程式

{{{
$ cat .profile
# ~/.profile: executed by the command interpreter for login shells.
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.

# the default umask is set in /etc/profile; for setting the umask
# for ssh logins, install and configure the libpam-umask package.
#umask 022

# if running bash
if [ -n "$BASH_VERSION" ]; then                #  如果 BASH_VERSION 環境變數有內容, 那麼就去執行 ~/.bashrc
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
        . "$HOME/.bashrc"
    fi
fi

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then                        # 如果家目錄中有 bin 目錄, 會被加入 PATH 環境變數
    PATH="$HOME/bin:$PATH"
fi
}}}

{{op1{2. ~/.bashrc}}}
每執行一次 bash 命令, 這個程式就會被執行一次

{{{
$ cat .bashrc
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

# don't put duplicate lines in the history. See bash(1) for more options
# ... or force ignoredups and ignorespace
HISTCONTROL=ignoredups:ignorespace

# append to the history file, don't overwrite it
shopt -s histappend

# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000

# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize

# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"

# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then
    debian_chroot=$(cat /etc/debian_chroot)
fi

# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
    xterm-color) color_prompt=yes;;
esac

# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
#force_color_prompt=yes

if [ -n "$force_color_prompt" ]; then
    if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
        # We have color support; assume it's compliant with Ecma-48
        # (ISO/IEC-6429). (Lack of such support is extremely rare, and such
        # a case would tend to support setf rather than setaf.)
        color_prompt=yes
    else
        color_prompt=
    fi
fi

if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt

# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
    ;;
*)
    ;;
esac

# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
    test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
    alias ls='ls --color=auto'
    #alias dir='dir --color=auto'
    #alias vdir='vdir --color=auto'

    alias grep='grep --color=auto'
    alias fgrep='fgrep --color=auto'
    alias egrep='egrep --color=auto'
fi

# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'

# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.

if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi

# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
    . /etc/bash_completion
fi

# 以下是學員自行加入的

alias dir='ls -al'
alias bye='sudo shutdown -h now'
alias ping='ping -c 4 '

setterm -blength 0 -blank 0

if [ -z $SSH_TTY ]; then
   export LANG='en_US.UTF-8'
   export LANGUAGE='en_US'
fi
}}}

{{op1{實作練習}}}

''1. 修改 ~/.profile 設定程式檔 (在檔案前面)''
{{{
                   :
echo "hi .profile"   > /tmp/student                 # 加入此行

if [ -n "$BASH_VERSION" ]; then      
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
        . "$HOME/.bashrc"
    fi
fi
                :
}}}

''2. 修改 ~/.bashrc 設定程式檔 (在檔案最後)''
{{{
                        :
echo "hi .bashrc"     >> /tmp/student      # 加入此行
}}}

''3. 重新登入''
{{{
$ cat /tmp/student
hi .profile                           #  證明 ~/.profile 先執行
hi bashrc
}}}

{{item1{編輯登入訊息檔 (Ubuntu Server)}}}
以下操作必須在 Ubuntu Server 系統中操作

''登入前訊息顯示''
{{{
$ cat /etc/issue
Ubuntu 10.04.1 LTS \n \l                              #  由此訊息也可以知道所使用 Ubuntu 的版本
}}}

''登入後訊息顯示''
{{{
$ cat /etc/motd
Linux oncloud9 2.6.32-21-generic-pae #32-Ubuntu SMP Fri Apr 16 09:39:35 UTC 2010 i686 GNU/Linux
Ubuntu 10.04.1 LTS

Welcome to Ubuntu!
 * Documentation:  https://help.ubuntu.com/

Your CPU appears to be lacking expected security protections.
Please check your BIOS settings, or for more information, run:
  /usr/bin/check-bios-nx --verbose

  System information as of Mon Aug  9 23:28:00 CST 2010

  System load:  0.45              Processes:           91
  Usage of /:   3.0% of 47.81GB   Users logged in:     1
  Memory usage: 7%                IP address for lo:   127.0.0.1
  Swap usage:   0%                IP address for eth0: 192.168.56.128

  Graph this data and manage this system at https://landscape.canonical.com/
}}}

''[註]'' Message of the Day (motd)

/etc/motd 這個檔案內容, 是由 /etc/update-motd.d/ 目錄中的所有程式所產生的, 你自己也可以在此目錄, 增加程式來顯示自己的資訊

''顯示 /etc/update-motd.d/ 目錄內容''
這目錄中的程式, 是在 ''登入前'' 會被執行
{{{
$ ls -al /etc/update-motd.d/
總計 36
drwxr-xr-x  2 root root 4096 2010-08-04 17:06 .
drwxr-xr-x 88 root root 4096 2010-08-05 22:46 ..
-rwxr-xr-x  1 root root   57 2010-04-23 17:45 00-header
-rwxr-xr-x  1 root root  248 2010-04-23 17:45 10-help-text
-rwxr-xr-x  1 root root   65 2010-04-14 04:45 20-cpu-checker
lrwxrwxrwx  1 root root   46 2010-08-04 17:06 50-landscape-sysinfo -> /usr/share/landscape/landscape-sysinfo.wrapper
-rwxr-xr-x  1 root root   71 2010-04-14 04:45 90-updates-available
-rwxr-xr-x  1 root root   61 2010-04-24 03:13 91-release-upgrade
-rwxr-xr-x  1 root root   69 2010-04-14 04:45 98-reboot-required
-rwxr-xr-x  1 root root  261 2010-04-23 17:45 99-footer
}}}

''顯示 00-header 程式內容''
{{{
$ cat /etc/update-motd.d/00-header
#!/bin/sh

uname -a
printf "%s\n" "$(lsb_release -s -d)"
}}}

''顯示 50-landscape-sysinfo 程式內容''
{{{
$ cat /etc/update-motd.d/50-landscape-sysinfo
#!/bin/sh
echo
echo -n "  System information as of "
/bin/date
echo
/usr/bin/landscape-sysinfo
}}}

''直接執行 /etc/update-motd.d/50-landscape-sysinfo 程式, 顯示如下 : ''
{{{
$ /etc/update-motd.d/50-landscape-sysinfo

  System information as of 四  8月  5 23:04:56 CST 2010

  System load:  0.0               Processes:           72
  Usage of /:   2.7% of 47.81GB   Users logged in:     1
  Memory usage: 6%                IP address for lo:   127.0.0.1
  Swap usage:   0%                IP address for eth0: 192.168.56.128

  Graph this data and manage this system at https://landscape.canonical.com/
}}}

''自製訊息程式''
{{{
$ cd /etc/update-motd.d
$ sudo nano 99-zhi
#!/bin/bash
echo hi

$ sudo chmod +x 99-zhi
$ sudo reboot
}}}

{{item1{取消登入後的訊息顯示}}}

在你的家目錄產生以下檔案 :
{{{
$ touch .hushlogin
}}}
<<toBalaNotes "bashs">>

///%bashs
//%/
{{item1{撰寫永不停止程式 (輸出數字到 /tmp/counter 檔)}}}
{{{
$ nano nostop01.sh
c=0; echo "" > /tmp/counter
while  [  true  ]
do 
   echo  "$c"  >>  /tmp/counter
   let  "c=$c+1"
done

$ chmod  +x  nostop01.sh
}}}

{{item1{背景執行 nostop01.sh 程序}}}
''1. 暫停 nostop01.sh 程序''
{{{
$ ./nostop01.sh                       
./nostop01.sh 
^Z                                                   (按 Ctrl+Z)
[1]+  Stopped                 ./nostop01.sh

student@US1041OC9:~/bin$ ps
  PID TTY          TIME CMD
 1016 ttyS0    00:00:00 bash
 1607 ttyS0    00:00:01 nostop01.sh
 1608 ttyS0    00:00:00 ps

$ tail /tmp/counter 
46949
46950
46951
46952
46953
46954
46955
46956
46957
46958
}}}

''2. 送到背景繼續執行''
{{{
$ bg
[1]+ ./nostop01.sh &

$ bg 1
-bash: bg: job 1 already in background

$ tail /tmp/counter 
514816
514817
514818
514819
514820
514821
514822
514823
514824
514825

$ tail /tmp/counter          (執行此命令確認 nostop01.sh 有在背景執行)
596761
596762
596763
596764
596765
596766
596767
596768
596769
596770
}}}

{{item1{中斷背景程序}}}
''結束 nostop01.sh 程序, 操作如下 : ''
{{{
# top  -i

# kill  -9  964
}}}
<<toBalaNotes "1">>

{{item1{背景執行應用工具}}}
{{{
# nano aaa.txt
按 “ctrl + z” 複合鍵, 暫停 nano 執行

# jobs
[1]+ Stopped     vi  aaa.txt

# fg 1
}}}

{{item1{直接背景執行命令 (root 身分)}}}
{{{
# find  /  -name  “*.txt”  &

# find  /  -name  “*.txt”  > /tmp/list  &

# tail  /tmp/list
}}}

{{item1{移除背景程序}}}
{{{
$ ps aux | grep find
root      2921  0.1  0.3   2648  1168 pts/0    T    23:52   0:00 sudo find / -name *.*
tobala    2928  0.0  0.2   3340   796 pts/0    S+   23:53   0:00 grep find

$ kill -9 2921
-bash: kill: (2921) - 此項操作並不被允許

$ sudo kill -9 2921
[5]+  已砍掉               sudo find / -name "*.*" > /tmp/all
}}}

<<toBalaNotes "2">>


///%1
//%/

///%2
//%/
{{item1{Uninstalling GRUB 2}}}
If a user chooses to return to GRUB legacy (0.97), these steps will remove GRUB 2 and install GRUB.

The command line produces a cleaner uninstall and reinstallation. While adding and removing the packages can be accomplished with Synaptic, certain steps must be accomplished in a terminal.

''1. Make backup copies of the main GRUB 2 directories and files.''
{{{
$ sudo cp /etc/default/grub /etc/default/grub.old
$ sudo cp -R /etc/grub.d /etc/grub.d.old
$ sudo cp -R /boot/grub /boot/grub.old 
}}}
 
''2. Remove GRUB 2''
{{{
$ sudo apt-get purge grub2 grub-pc
}}}
[img[img/ubuntu10.4/Server/removegrub2.png]]

''3. Install GRUB 0.97''
{{{
$ sudo apt-get install grub
正在讀取套件清單... 完成
正在重建相依關係
正在讀取狀態資料... 完成
建議套件:
  grub-legacy-doc mdadm
下列【新】套件將會被安裝:
  grub
升級 0 個,新安裝 1 個,移除 0 個,有 3 個未被升級。
需要下載 406kB 的套件檔。
此操作完成之後,會多佔用 946kB 的磁碟空間。
下載:1 http://tw.archive.ubuntu.com/ubuntu/ lucid/main grub 0.97-29ubuntu60 [406kB]
取得 406kB 用了 3s (107kB/s)
正在預先設定套件 ...
選取了原先未被選取的套件 grub。
(正在讀取資料庫 ... 系統目前共安裝了 42393 個檔案和目錄。)
正在解開 grub (從 .../grub_0.97-29ubuntu60_i386.deb)...
正在進行 man-db 的觸發程式 ...
正在設定 grub (0.97-29ubuntu60) ...
}}}
   
''4. With grub installed, the user must still create the menu.lst and stage1/stage2 files by running the following two commands.''
{{{
$ sudo update-grub
Searching for GRUB installation directory ... found: /boot/grub
Searching for default file ... Generating /boot/grub/default file and setting the default boot entry to 0
Searching for GRUB installation directory ... found: /boot/grub
Testing for an existing GRUB menu.lst file ...

Could not find /boot/grub/menu.lst file. Would you like /boot/grub/menu.lst generated for you? (y/N) y
Searching for splash image ... none found, skipping ...
Found GRUB 2: /boot/grub/core.img
Found kernel: /boot/memtest86+.bin
Found kernel: /boot/vmlinuz-2.6.32-21-generic-pae
Found GRUB 2: /boot/grub/core.img
Found kernel: /boot/memtest86+.bin
Updating /boot/grub/menu.lst ... done

$ sudo grub-install /dev/sda
Searching for GRUB installation directory ... found: /boot/grub
Unknown partition table signature
Unknown partition table signature
   :
Unknown partition table signature
Unknown partition table signature
Installing GRUB to /dev/sda as (hd0)...
Unknown partition table signature
Installation finished. No error reported.
This is the contents of the device map /boot/grub/device.map.
Check if this is correct or not. If any of the lines is incorrect,
fix it and re-run the script `grub-install'.

(fd0)   /dev/fd0
(hd0)   /dev/sda
}}}

Choose the correct device (sda, sdb, etc), normally the one on which Ubuntu is installed.Creates the stage1 and stage2 files in /boot/grub and writes to the MBR. 

''5. Reboot''
{{{
$ sudo reboot
}}}
<<toBalaNotes "back2grub">>

///%back2grub
//%/
''參考文章''
1. Anatomy of the Linux file system
http://www.ibm.com/developerworks/linux/library/l-linux-filesystem/

{{item1{ext2}}}
自從我們開始使用電腦後,大多數的使用者都曾經使用過檔案,而我們總是對關於硬碟如何正確地儲存檔案感到好奇,它看起來似乎非常抽象,所以今天讓我們看一看 Linux 作業系統中較新的檔案系統版本『第二延伸系統( ext2 )』,並了解它各方面之用途。

這個檔案系統是主要來自於 Andrew Tanenbaum 所寫的 Minix 檔案系統,它也是唯一可用在免費作業系統的檔案系統,稱之為 Minix。它後來修正為 Linux 所慣用的檔案系統並稱為延伸檔案系統,到現在 Linux 的檔案系統稱為 ext2 (第二延伸檔案系統),它是延伸檔案系統中較新的版本並支援存取控制列 (ACL)。

但是在著手研究 ext2 檔案系統之前,讓我們先了解檔案系統中之專有名詞的關聯。

{{op1{Block (區塊)}}}
檔案在磁碟中被儲存在整數固定大小的區塊中, 那區塊的大小通常是 2 的次方。在預設中,ext2 檔案系統的區塊大小是 4 K。研究顥示, 4K 位元組對於一磁碟區塊而言是最理想的大小,假如一個檔案的大小無法達成 4K 位元組的倍數時, 那最後的磁碟區塊部分就會被浪費。在最不好的例子中幾乎在完整的區塊中就有一位元組被浪費掉。

對於這情況有一點技巧,假如我們選擇了一個較大的區塊,則對於小的檔案而言會有一些磁碟空間被浪費掉。 另外一方面,假如我們使用一個非常小的區塊,則磁碟區塊數量會成指數的增加, 因此對於檔案而言需有更多的搜尋時間。所以,選擇區塊大小必須三思而後行。

當一個檔案被載入到記憶體時,那磁碟區塊會被放在主記憶體中之緩衝快取區,假如它們已經變更了, 區塊在緩衝區中會被標記為 ’Dirty’, 其意指的是這些區塊必須先寫到磁碟中來維持磁碟上的區塊及在主記憶體中的區塊之一致性.

{{op1{Superblock (一個檔案系統只有一個)}}}
superblock 是在每個檔案系統開始的位置, 其儲存資訊像是檔案系統的大小,空的和填滿的區塊,它們各自的總數和其他諸如此類的資料。 要從一個檔案系統中存取任何檔案皆須經過檔案系統中之 superblock。如果 superblock 損壞了, 它可能無法從磁碟中去取得資料。

{{op1{Inode (一個檔案會有一個 inode)}}}
對於檔案系統而言一個 inode 是在 inode 表格中的一個項目。 Inode 包含了所有檔案有關的資訊例如名稱、大小、連接的數量、資料建立之日期,修改及存取的時間。 它也包含了磁碟區塊的檔案指向(pointer)。pointer 是用來記錄檔案被儲存在何處。

''顯示硬碟檔案系統資訊''
{{{
$ sudo blockdev --getss /dev/sda
512
$ sudo blockdev --getsz /dev/sda
1953525168
$ sudo blockdev --getbsz /dev/sda
4096
}}}

''blockdev 命令參數''
{{{
Available commands:
        --getsz                        get size in 512-byte sectors
        --setro                        設成唯讀
        --setrw                        set read-write
        --getro                        get read-only
        --getss                        get sectorsize
        --getbsz                       get blocksize
        --setbsz BLOCKSIZE             set blocksize
        --getsize                      get 32-bit sector count
        --getsize64                    get size in bytes
        --setra READAHEAD              set readahead
        --getra                        get readahead
        --setfra FSREADAHEAD           set filesystem readahead
        --getfra                       get filesystem readahead
        --flushbufs                    flush buffers
        --rereadpt                     reread partition table
}}}

{{item1{ext3}}}
維基百科網址 : http://en.wikipedia.org/wiki/Ext3

The ext3 or third extended filesystem is a journaled file system that is commonly used by the Linux kernel. It is the default file system for many popular Linux distributions. Stephen Tweedie first revealed that he was working on extending ext2 in Journaling the Linux ext2fs Filesystem in a 1998 paper and later in a February 1999 kernel mailing list posting, and the filesystem was merged with the mainline Linux kernel in November 2001 from 2.4.15 onward.[2][3][4] Its main advantage over ext2 is journaling which improves reliability and eliminates the need to check the file system after an unclean shutdown. Its successor is ext4.

{{item1{ext4}}}
維基百科網址 : http://en.wikipedia.org/wiki/Ext4

The ext4 or fourth extended filesystem is a journaling file system for Linux, developed as the successor to ext3.

It was born as a series of backward compatible extensions to remove 64-bit storage limits and add other performance improvements to ext3. However, other Linux kernel developers opposed accepting extensions to ext3 for stability reasons, and proposed to fork the source code of ext3, rename it as ext4, and do all the development there, without affecting the current ext3 users. This proposal was accepted, and on 28 June 2006, Theodore Ts'o, the ext3 maintainer, announced the new plan of development for ext4.

A preliminary development version of ext4 was included in version 2.6.19 of the Linux kernel. On 11 October 2008, the patches that mark ext4 as stable code were merged in the Linux 2.6.28 source code repositories, denoting the end of the development phase and recommending ext4 adoption. Kernel 2.6.28, containing the ext4 filesystem, was finally released on 25 December 2008. On 15 January 2010, Google announced that it would upgrade its storage infrastructure from ext2 to ext4.

<<toBalaNotes "ext">>


///%ext
//%/
''參考文章''
1. Gentoo Sudo(ers) Guide
http://www.gentoo.org/doc/en/sudo-guide.xml
2. PAM 範例
http://benjr.tw/?q=node/97

{{item1{su 命令}}}
''su: Run a command with substitute user and group ID''

"su" allows one user to temporarily become another user.  It runs a command (often an interactive shell) with the real and effective user ID, group ID, and supplemental groups of a given USER.  Synopsis:
{{{
su [OPTION]... [USER [ARG]...]
}}}

If no USER is given, the default is ''root'', the super-user.  The shell to use is taken from USER's passwd entry, or /bin/sh if none is specified there.  If USER has a password, su prompts for the password unless run by a user with effective user ID of zero (the super-user).

''1. 設定 root 帳號的密碼''
{{{
cloudwalker@oncloud9:~$ sudo passwd root
[sudo] password for cloudwalker:                        (這是輸入 cloudwalker 帳號的密碼, 不是 root 帳號的新密碼)
輸入新的 UNIX 密碼:
再次輸入新的 UNIX 密碼:
passwd: password updated successfully
}}}

''2. 切換為 root 身份''
{{{
cloudwalker@oncloud9:~$ su -
密碼:                                             (這裡是輸入 root 帳號的密碼)
root@oncloud9:~# pwd                      (內定會在 root 的家目錄)
/root
root@oncloud9:~# echo $USER
root
root@oncloud9:~# exit                     (恢復原先身份)
logout
cloudwalker@oncloud9:~$
}}}

''[註]'' 執行 "su -" 命令, 必須知道 root 帳號的密碼

{{item1{身份切換與環境變數}}}
{{op1{1. 顯示目前登入使用者的環境變數}}}
''$ export PATH=$PATH:/home/profx/public_html''

''$ export ABC=XYZ''

''$ env | head -n 10''
{{{
ABC=XYZ
TERM=xterm
SHELL=/bin/bash
SSH_CLIENT=192.168.200.1 1484 22
SSH_TTY=/dev/pts/0
USER=profx
LS_COLORS=no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.svgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;
                                      :
MAIL=/var/mail/profx
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/profx/public_html
PWD=/home/profx
}}}

{{op1{2. 切換為 root 身份}}}
''$ su     (保留全域變數 ABC)''  
{{{
Password:           輸入 root 帳號的密碼 
}}}

''# env | head -n 10''
{{{
ABC=XYZ
SHELL=/bin/bash
TERM=xterm
SSH_CLIENT=192.168.200.1 1484 22
SSH_TTY=/dev/pts/0
USER=root
LS_COLORS=no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.svgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01; 
                                                               :
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
MAIL=/var/mail/root
PWD=/home/profx
# exit
exit
}}}

''[注意]'' 切換為 root 身份, 其環境變數, 還存有之前使用者的環境變數 (ABC), 但 PATH 並沒有保留之前使用者的內容

{{op1{3. 再次切換為 root 身份}}}
不再有之前使用者的任何環境變數

''$ su -     (不保留全域變數 ABC)''
{{{
Password:
}}}

''[注意]'' root 家目錄 (/root) 中的 .bashrc 會被執行

''# env | head -n 10''
{{{
SHELL=/bin/bash
TERM=xterm
USER=root
LS_COLORS=no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.svgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz2=01;31:*.tz=01; 
                                                          :
MAIL=/var/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/root
LANG=C
SHLVL=1
HOME=/root
}}}

{{item1{How To Auto Logout User In Linux After Certain Minutes Of Idle}}}
本文網址 : http://www.walkernews.net/2007/05/15/how-to-auto-logout-user-in-linux/

Don’t worry. There is no tedious configuration or additional package to be installed to make this happen.In fact, the simplest way is to configure the ''TMOUT'' environment variable !

For example
{{{
$ su -
Password:
# export TMOUT=10
# timed out waiting for input: auto-logout
}}}

will immediately get the Linux OS to automatically logout an user after his/her login session being idle for 10 seconds 
{{{
The TMOUT environment variable is applied to a command line console login session only.
For X-window or GUI login, you can easily turn on any pretty auto-lock screen-saver, that works very much like those in Windows.
}}}

For testing purpose, you can set a lower limit. While login to Linux, su to another user ID and execute
{{{
export TMOUT=10
}}}

In order the apply TMOUT to all Linux login accounts, you can put that export command to the login scripts or login profile ''(.bash_profile or .bashrc)'' in respective user home directory.

But, the easiest way is to write the export command in the system profile (/etc/profile) instead of respective user’s profile !
That’s to say, you can append the export TMOUT=60 command to ''/etc/profile'' (i.e. the system profile)!

Bear in mind that any login user can simply overwrite this TMOUT setting!

For example, he or she can easily disable or extend the time-out value before auto-logout feature triggered. To disable the Linux auto-logout user feature, just set the TMOUT to zero, i.e.
{{{
export TMOUT=0      取消 timeout 功能
}}}
In addition, the Linux TMOUT environment variable will not effective if the user has an active or open document. For example, if the VI editor is open, the Linux auto-logout feature in command console will not working!

{{item1{限定可執行 su 命令的使用者}}}

在 Ubuntu 系統, 新增的帳號是可以執行 su 命令, 執行以下設定, 便可限定執行 su 命令的使用者

''$ sudo nano /etc/pam.d/su''
{{{
[sudo] password for profx:
}}}

''請將 auth required   pam_wheel.so 這行的備註拿掉, 並加入 group=tobala, 如下圖''

[img[img/linux/sulimit.png]]

{{op1{將 profx 帳號, 加入 tobala 群組}}}
{{{
$ sudo groupadd tobala
$ sudo usermod -G tobala profx
}}}

{{op1{profx 帳號, 便可執行 su 命令}}}
{{{
$ su
Password:
root@ubuntu:/home/profx# exit
exit
}}}

<<toBalaNotes "su">>


///%su
//%/
{{item1{第一階段 : 取出網卡資訊}}}

''1. 取出所有網卡名稱''
{{{
$ ifconfig -a | grep eth > /tmp/net.txt

$ cat /tmp/net.txt | cut -d ' ' -f1        (一行顯示一個網卡名稱)

$ cat /tmp/net.txt | cut -d ' ' -f1 | fmt -u

}}}

''2. 顯示網卡 IP 資訊 (版本 0.1)''
{{{
$ nano showip.sh
#!/bin/bash

ifconfig -a | grep eth > /tmp/net.txt
n=$(cat /tmp/net.txt | cut -d ' ' -f1 | fmt -u)
echo $n

for  e  in $n
do
    ip=$(ifconfig -a | grep -A1 $e | grep 'inet addr')
    ip=${ip#*:}
    ip=${ip%% *}
    echo $ip
done
}}}

<<toBalaNotes "1">>

{{item1{第二階段 : 確認網卡 IP 取得方式}}}

''1. 使用 grep 命令, 取出網卡 IP 取得方式 (dhcp, static)''
{{{
$ cat /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet dhcp

auto eth1
iface eth1 inet static
  address 192.168.233.12
  netmask 255.255.255.0

$ cat /etc/network/interfaces | grep 'eth1.*dhcp'   (eth1 不是使用 dhcp)

$ cat /etc/network/interfaces | grep 'eth0.*dhcp'   (有顯示資訊, 代表 eth0 使用 dhcp)
iface eth0 inet dhcp
$ echo $?
0
}}}

''2. 顯示網卡資訊 (版本 0.2)''
{{{
$ nano showip.sh
#!/bin/bash

ifconfig -a | grep eth > /tmp/net.txt
n=$(cat /tmp/net.txt | cut -d ' ' -f1 | fmt -u)

for  e  in $n
do
    ip=$(ifconfig -a | grep -A1 $e | grep 'inet addr')
    ip=${ip#*:}
    ip=${ip%% *}

    cat /etc/network/interfaces | grep "$e.*dhcp" &>/dev/null
    if [ "$?" == "0" ]; then
       echo "$e : $ip (dhcp)"
    else
       echo "$e : $ip"
    fi

done

$ bash showip.sh
eth0 : 192.168.56.128 (dhcp)
eth1 : 192.168.233.12
}}}

@@color:red;''[問題]'' 如網卡沒有位址, 上述程式如何修改 ?@@

<<toBalaNotes "2">>

{{item1{第三階段 :  重設 IP 位址}}}

''1. 使用 sed 命令, 置換 IP 位址''
{{{
$ cat /etc/network/interfaces | sed 's/192.168.233.12/192.168.233.14/'

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet dhcp

auto eth1
iface eth1 inet static
  address 192.168.233.14
  netmask 255.255.255.0
}}}

''2. 修改 IP 位址 (沒有寫回 /etc/network/interfaces)''
{{{
$ nano chgip.sh
#!/bin/bash

ifconfig -a | grep eth > /tmp/chgip.tmp
n=$(cat /tmp/chgip.tmp | cut -d ' ' -f1 | fmt -u)

for  e  in $n
do
    ip=$(ifconfig -a | grep -A1 $e | grep 'inet addr')
    ip=${ip#*:}
    ip=${ip%% *}

    cat /etc/network/interfaces | grep "$e.*dhcp" &>/dev/null
    if [ "$?" == "0" ]; then
       echo "$e : $ip (dhcp)"
    else
       echo "$e : $ip"
       read -p "change ip (y/n) " ans
       if [ "$ans" == "y" ]; then
          read -p "New IP Address : " nip
          cat /etc/network/interfaces | sed "s/$ip/$nip/"
       fi
    fi
done
}}}

''3. 最終版''
{{{
$ nano chgip.sh
#!/bin/bash

#  必須是 root 帳號執行
[ "$USER" != "root"  ] && echo "need root" && exit 1                      

ifconfig -a | grep eth > /tmp/net.txt
n=$(cat /tmp/net.txt | cut -d ' ' -f1 | fmt -u)

for  e  in $n
do
    ip=$(ifconfig -a | grep -A1 $e | grep 'inet addr')
    ip=${ip#*:}
    ip=${ip%% *}

    cat /etc/network/interfaces | grep "$e.*dhcp" &>/dev/null
    if [ "$?" == "0" ]; then
       echo "$e : $ip (dhcp)"
    else
       echo "$e : $ip"
       read -p "change ip (y/n) " ans
       if [ "$ans" == "y" ]; then
          read -p "New IP Address : " nip
           #  將修改後的結果, 寫入 /tmp/chgip.tmp
          cat /etc/network/interfaces | sed "s/$ip/$nip/" &> /tmp/chgip.tmp     
         
          #  將 /tmp/chgip.tmp 覆蓋 /etc/network/interfaces
          [ "$?" == 0 ] && cp /tmp/chgip.tmp /etc/network/interfaces           
          # ifdown $e
          # ifup $e
       fi
    fi
done

exit 0
}}}
<<toBalaNotes "3">>


///%1
//%/

///%2
//%/

///%3
//%/
{{item1{LPIC 相關部落格}}}
1. Figaro Yang
http://figaro.neo-info.net/?page_id=2


Neatx 官方網站 : http://code.google.com/p/neatx/

本文網址 : https://help.ubuntu.com/community/FreeNX

Neatx is an Open Source NX server, similar to the commercial NX server from NoMachine. 

''History''
Neatx was developed by Google for an internal project. That project is now finished, and the source was released for the community to use/develop/benefit from. A couple of Google employees are doing sporadic releases and maintenance in their spare time.

''What Works''
{{{
* Session creation
* Session suspension
* Session resumption
* Session shutdown
* Gnome/KDE/Application/Console sessions
* Floating Window/Virtual Desktop sessions
* Fullscreen/Resolution/Keyboard preferences
* Session shadowing (though only sessions belonging to you) 
}}}

<<toBalaNotes "neatx">>

{{item1{安裝 Neatx Server}}}
''1. 增加套件庫''
{{{
$ sudo apt-get install python-software-properties && sudo add-apt-repository ppa:freenx-team
正在讀取套件清單... 完成
正在重建相依關係
正在讀取狀態資料... 完成
python-software-properties 已經是最新版本了。
以下套件是被自動安裝進來的,且已不再會被用到了:
  linux-headers-2.6.32-21 linux-headers-2.6.32-22 linux-headers-2.6.32-22-generic-pae
使用 'apt-get autoremove' 來將其移除。
升級 0 個,新安裝 0 個,移除 0 個,有 5 個未被升級。
Executing: gpg --ignore-time-conflict --no-options --no-default-keyring --secret-keyring /etc/apt/secring.gpg --trustdb-name /etc/apt/trustdb.gpg --keyring /etc/apt/trusted.gpg --primary-keyring /etc/apt/trusted.gpg --keyserver keyserver.ubuntu.com --recv F3A662B57D580D3A2E98E5152A8E3034D018A4CE
gpg: 正在請求金鑰 D018A4CE 自 hkp 伺服器 keyserver.ubuntu.com
gpg: 金鑰 D018A4CE: 公鑰 "Launchpad PPA for FreeNX Team" 已匯入
gpg: 處理總量: 1
gpg:               已匯入: 1  (RSA: 1)
}}}

''2. 更新套件清單''
{{{
$ sudo apt-get update
}}}

At this point, the repository is added and apt is updated, then install the neatx-server package.

''3. 安裝 NeatX Server''
{{{
$ sudo apt-get install neatx-server
正在讀取套件清單... 完成
正在重建相依關係
正在讀取狀態資料... 完成
以下套件是被自動安裝進來的,且已不再會被用到了:
  linux-headers-2.6.32-21 linux-headers-2.6.32-22 linux-headers-2.6.32-22-generic-pae
使用 'apt-get autoremove' 來將其移除。
下列的額外套件將被安裝:
  libxcomp3 libxcompext3 libxcompshad3 nx-common nxagent nxlibs python-neatx
下列【新】套件將會被安裝:
  libxcomp3 libxcompext3 libxcompshad3 neatx-server nx-common nxagent nxlibs python-neatx
升級 0 個,新安裝 8 個,移除 0 個,有 5 個未被升級。
需要下載 2,940kB 的套件檔。
此操作完成之後,會多佔用 7,733kB 的磁碟空間。
是否繼續進行 [Y/n]?
}}}

{{item1{安裝 NX Client for Windows}}}

''1. 下載 NX Client for Windows''
下載網址 : http://www.nomachine.com/select-package-client.php

''2. 安裝  NX Client for Windows''

[img[img/neatx/client01.png]]

[img[img/neatx/client02.png]]

''3. 連接遠端桌面''

[img[img/neatx/client03.png]]

[img[img/neatx/client04.png]]

''4. 操作桌面''

[img[img/neatx/client05.png]]

{{item1{問與答}}}
''Q1 : 使用 Neatx Client 連接 Neatx Server, 出現以下錯誤訊息''
{{{
NX> 148 Server capacity: not reached for user: root
NX> 105 Restoresession  --link="adsl" --backingstore="1" --encryption="1" --cache="16m" --images="64m" --shmem="1" --shpix="1" --strict="0" --composite="1" --media="0" --session="ud252" --type="unix-gnome" --geometry="900x600" --client="winnt" --keyboard="pc102/us" --id="d80666995a069f8350074440c8a3ca96" --resize="1"
NX> 500 Internal error
NX> 999 Bye.
NX> 280 Exiting on signal: 15
}}}

''A1 : 請將 /var/lib/neatx/sessions 目錄中的所有目錄刪除''
{{{
# ls -al /var/lib/neatx/sessions
總計 36
drwxrwxrwt 9 root    root    4096 2010-08-05 10:35 .
drwxr-xr-x 3 root    root    4096 2010-07-30 16:43 ..
drwx------ 4 root    root    4096 2010-08-04 16:44 006585FE6EE2A053295C846CEDA16F7F
drwx------ 4 root    root    4096 2010-08-05 16:21 1D1C7CDF934BB553676CDBD733A2A294
drwx------ 4 student student 4096 2010-07-30 17:08 266ABDEA5E1803E07AB389F3BE9FF293
drwx------ 4 root    root    4096 2010-08-02 22:41 6D6500B727CEB50301FDB3C74644ECF5
drwx------ 4 root    root    4096 2010-08-01 23:54 7A0E095521405668692794F394E675F6
drwx------ 4 root    root    4096 2010-08-02 23:37 F191AAE99A6AF7575080558055177745
drwx------ 4 student student 4096 2010-07-30 17:17 FFAACB2E98C6300C7E5B9989266E1FF0

# sudo rm /var/lib/neatx/sessions/*
rm: 無法建立目錄「/var/lib/neatx/sessions/006585FE6EE2A053295C846CEDA16F7F」: 是個目錄
rm: 無法建立目錄「/var/lib/neatx/sessions/1D1C7CDF934BB553676CDBD733A2A294」: 是個目錄
rm: 無法建立目錄「/var/lib/neatx/sessions/266ABDEA5E1803E07AB389F3BE9FF293」: 是個目錄
rm: 無法建立目錄「/var/lib/neatx/sessions/6D6500B727CEB50301FDB3C74644ECF5」: 是個目錄
rm: 無法建立目錄「/var/lib/neatx/sessions/7A0E095521405668692794F394E675F6」: 是個目錄
rm: 無法建立目錄「/var/lib/neatx/sessions/F191AAE99A6AF7575080558055177745」: 是個目錄
rm: 無法建立目錄「/var/lib/neatx/sessions/FFAACB2E98C6300C7E5B9989266E1FF0」: 是個目錄

# sudo rm -R /var/lib/neatx/sessions/*

}}}

///%neatx
//%/
{{item1{SUN JDK1.6 套件安裝}}} 
從 Ubuntu 10.04 版開始, Sun Java 開發套件已移到 Partner repository, 安裝說明如下 : 

For Ubuntu 10.04 LTS, the ''sun-java6-jdk'' packages have been dropped from the Multiverse section of the Ubuntu archive. It is recommended that you use ''openjdk-6'' instead.

If you can not switch from the proprietary Sun JDK/JRE to OpenJDK, you can install ''sun-java6-jdk'' packages from the Canonical Partner Repository. You can configure your system to use this repository via command-line:
{{{
$ add-apt-repository "deb http://archive.canonical.com/ lucid partner"
}}}
執行完上述命令後, 在 /etc/apt/source.list 檔案的最後, 會自動加入下式 : 
{{{
$ deb http://archive.canonical.com/ lucid partner
}}}
重新更新套件資料庫
{{{
$ sudo apt-get update
}}}
安裝 SUN JDK6
{{{
$ apt-get install sun-java6-jdk
}}}
檢視 JDK 版本代號
{{{
$ java -version
}}}

{{item1{shellinabox}}}
{{{
$ wget http://shellinabox.googlecode.com/files/shellinabox_2.10-1_i386.deb
--2010-09-24 23:38:19--  http://shellinabox.googlecode.com/files/shellinabox_2.10-1_i386.deb
正在查找主機 shellinabox.googlecode.com... 72.14.203.82
正在連接 shellinabox.googlecode.com|72.14.203.82|:80... 連上了。
已送出 HTTP 要求,正在等候回應... 200 OK
長度: 124070 (121K) [application/x-archive application/x-debian-package]
Saving to: `shellinabox_2.10-1_i386.deb'

100%[======================================>] 124,070      110K/s   in 1.1s

2010-09-24 23:38:21 (110 KB/s) - `shellinabox_2.10-1_i386.deb' saved [124070/124070]


$ dpkg -i shellinabox_2.10-1_i386.deb
dpkg: 該操作需要超級使用者權限
student@US1041OC9:~$ sudo dpkg -i shellinabox_2.10-1_i386.deb
選取了原先未被選取的套件 shellinabox。
(正在讀取資料庫 ... 系統目前共安裝了 44091 個檔案和目錄。)
正在解開 shellinabox (從 shellinabox_2.10-1_i386.deb)...
正在設定 shellinabox (2.10-1) ...
 * Starting Shell In A Box Daemon shellinabox                            [ OK ]

正在進行 ureadahead 的觸發程式 ...
ureadahead will be reprofiled on next reboot
正在進行 man-db 的觸發程式 ...

}}}

{{item1{APTonCD (適用 Desktop 版本)}}}
官方網址 : http://aptoncd.sourceforge.net/
文件網址 : http://wiki.ubuntu-tw.org/index.php?title=APTonCD

APTonCD 是 deb 套件備份軟體,讓使用者將已安裝及下載好的 deb 套件,打包成映像檔,燒錄備份至光碟上,以便於還原使用。 (註:APTonCD 套件快取目錄: /var/cache/apt/archives/ ) 



<<list shadowed>>

''參考文章''
1. 深入理解 Linux 2.6 的 initramfs 機制 (上)
http://blog.linux.org.tw/~jserv/archives/001954.html
2. Linux initial RAM disk (initrd) overview
http://www.ibm.com/developerworks/linux/library/l-initrd.html

本文網址 : http://www.indiangnu.org/2009/how-to-create-editextract-initrd-in-ubuntudebian-and-redhatfedora-linux/

{{item1{Introduction}}}
Long back I edited initrd as old linux (Ubuntu 9.04) box was not able to boot with SCSI hard disk? One of my friend wanted to do the same for other purpose. So got a chance to write article on the same? Let’s start with what is initrd?

{{op1{What is initrd ?}}}
initrd (Initial Ram Disk) is a temporary file system ( used as /) commonly used in the boot process of the Linux kernel. It is typically used for making preparations before the real root file system can be mounted.

{{op1{Why someone want to edit/modify initrd ?}}}
I assume that you all are familier with Linux booting process? Once Linux kernel loaded in to memory (RAM) it start init (father/mother of all  process) process. is that true? Let me ask you one question. Before loading actual physical root file system (/) how kernel access /sbin/init script? what is the use by specifying “initrd” file in GRUB ?  hold on!!

Suppose your root partion resides on some SCSI device and driver for this SCSI devices is compiled as a kernel module. Of course this module is required at boot time to have access to the root partion — but it is not in the kernel. Thus the need for an initrd image. Additionally after udev subsystem become common, somebody has to start udev to create device nodes. This is initrd’s duty too.

{{op1{See the GRUB menu as shown below}}}
{{{
menuentry "Ubuntu, linux 2.6.28-13-generic" {
       linux   /boot/vmlinuz-2.6.28-13-generic root=UUID=b02e1934-12dd-418a ro  quiet splash vga800
       initrd  /boot/initrd.img-2.6.28-13-generic
}
}}}
GRUB loads  kernel and initrd image in to memory(RAM). When kernel boots  it checks for initrd image, and if it exists starts init script that resides on this image. init script is usually written in bash. When init script on initrd image is finished, kernel usually start standard init process ie /sbin/init

''Step 1 Copy original initrd image file to home directory''
Create temporary directory and copy initrd file in that temp directory
{{{
$ cp /boot/initrd.img-2.6.32-21-generic-pae  ~
$ mkdir initrd-src
}}}

Now extract “initrd” image
{{{
$ cd initrd-src

$ gzip -dc  ../initrd.img-2.6.28-11-generic  | cpio -id
38791 blocks

$ ls -l
total 36
drwxr-xr-x 2 arunsb arunsb 4096 2009-07-12 16:32 bin
drwxr-xr-x 3 arunsb arunsb 4096 2009-07-12 16:32 conf
drwxr-xr-x 6 arunsb arunsb 4096 2009-07-12 16:32 etc
-rwxr-xr-x 1 arunsb arunsb 4825 2009-07-12 16:32 init
drwxr-xr-x 5 arunsb arunsb 4096 2009-07-12 16:32 lib
drwxr-xr-x 2 arunsb arunsb 4096 2009-07-12 16:32 sbin
drwxr-xr-x 8 arunsb arunsb 4096 2009-07-12 16:32 scripts
drwxr-xr-x 3 arunsb arunsb 4096 2009-07-12 16:32 usr
}}}

[img[img/ubuntu10.4/Server/initrdir.png]]

Check how “init” looks like
{{{
arunsb@laptop:/tmp/initrd-src$ head init
#!/bin/sh

echo “Loading, please wait…”

[ -d /dev ] || mkdir -m 0755 /dev
[ -d /root ] || mkdir -m 0700 /root
[ -d /sys ] || mkdir /sys
[ -d /proc ] || mkdir /proc
[ -d /tmp ] || mkdir /tmp
mkdir -p /var/lock
}}}

''Step 2 Edit/Modify as per your requirement''

''Step 3 How to create initrd image''

Create initrd image from scratch -
{{{
$ mkinitramfs  -v -o  /tmp/initrd-oc9-$(uname -r)        // 增加驅動程式與系統命令
                             :
Adding module /lib/modules/2.6.32-21-generic-pae/kernel/drivers/ata/pata_hpt366.ko
Adding module /lib/modules/2.6.32-21-generic-pae/kernel/drivers/ata/sata_mv.ko
Adding module /lib/modules/2.6.32-21-generic-pae/kernel/drivers/firewire/firewire-core.ko
Adding module /lib/modules/2.6.32-21-generic-pae/kernel/drivers/firewire/firewire-ohci.ko
Adding module /lib/modules/2.6.32-21-generic-pae/kernel/drivers/firewire/firewire-sbp2.ko
Adding binary /usr/share/initramfs-tools/init
                              :
Adding library /lib/libudev.so.0
Adding binary /sbin/modprobe
Adding binary /sbin/depmod
Adding binary /sbin/rmmod
Adding binary /sbin/blkid
Adding library /lib/libblkid.so.1
Adding library /lib/libuuid.so.1

$ du -sh /tmp/initrd-oc9-2.6.28-11-generic
7.2M    /tmp/initrd-oc9-2.6.28-11-generic
}}}
''[註] mkinitramfs'' : is the tool used to create initrd image. “initrd” image is a gzipped cpio archive.

After all modifcation create initrd image as shown below…
{{{
$ find . | cpio --quiet --dereference -o -H newc | gzip -9 > /tmp/initrd-oc9-2.6.32-21-generic-pae

$ ls -l /tmp/tmp/initrd-oc9-2.6.32-21-generic-pae
-rw-r–r– 1 arunsb arunsb 7505955 2009-07-12 16:56 tmp/initrd-oc9-2.6.32-21-generic-pae
}}}

<<toBalaNotes "initrd">>


///%initrd
//%/
本文網址 : http://www.linux.com/archive/feed/40433

Your ''home directory'' is the place where you keep your own files. Good organizational skills and some foresight will help keep your "home" in order. 
''顯示家目錄內容''
{{{
cloudwalker@oncloud9:~$ tree -al
.
├── .bash_history
├── .bash_logout
├── .bashrc
├── .cache
│         └── motd.legal-displayed
├── .profile
└── .sudo_as_admin_successful

7 directories, 6 files
}}}

{{item1{Using a directory for personal binaries}}}

A directory for binaries is simply a directory where you store executable files. To make the shell recognize it, add this directory to your path variable, as defined in your ''~/.bashrc'' file. The directory can have any name. I prefer sticking with the bin convention and putting it right in the home directory: ''~/bin.''

''To make your own bin directory and add it to your path, do the following:''

Use mkdir to make a bin directory in your home directory:
{{{
$ mkdir ~/bin
}}}

In your own bin, you can put scripts and tools of your own devising. They will be executable by you, but by no other users on the system. To make a file executable by all users, the superuser will have to put the file in ''/usr/local/bin'', the system-wide local directory for binaries.

''[註]'' The current shell won't recognize any changes you make in your .bashrc; you'll have to run it by hand the first time, or just exit and start a new shell.

{{item1{Using a directory for personal lists and data}}}
Everybody has his own set of personal files containing lists, data, and other "configurations," such as passwords, accounts and pass-phrases, account information, addresses, and so on. These are good things to put in a directory named etc. Some people might like using personal or per for this instead, but regardless of the name, I find that having a directory for expressly this purpose is very handy.

This is a good place to keep the kinds of files listed in the following table.

|address or contacts|Address book|
|appointments or todo or TODO|To-do list. Uppercase file names are sorted first in directory listings.|
|birthdays|List of birthdays.|
|calendar|personal calendar file. You can keep specialized calendars for your interests, such as calendar.birthdays or calendar.wwii.|
|crontab|Personal cron table file.|
|passwd or passwords|Personal password file. Be sure to change its permissions so that nobody else can look at it.|
|quotes|Favorite quotations.|

''Using a directory for mail''
You will probably want a directory to keep all your email correspondence, including both incoming and outgoing mail. Most people use either Mail or mail as the name of this directory; many email applications use one name or the other as the default for storing messages. You can build subdirectories in here to store messages away in neater folders, such as outgoing for outgoing mail, family for family correspondence, and projects for project mail.

''Using a directory for projects''
It is sometimes desirable to keep a group of files together when working on a project of some sort. Depending on your work and enterprise, you might like to make a directory for your projects -- say, jobs, projects, work, drafts, or research, depending on what you do, and make subdirectories in it for any particular project or job you are working on.

Programmers usually have a src directory for computer program source code; other common directories for special work that you may want to consider include photos or photographs, art or images, books, and music or recordings. Hobbyists might keep scrapbook or craft directories.

These main categories may, in turn, contain directories for particular projects, and those project directories may contain their own src directory for source files, doc for documentation, a THANKS file for acknowledgements, and so on.

''Using a directory for temporary files''
You might like to have a directory that you use as a kind of "holding pen" to bring in new files that perhaps should be processed soon, but not right at the moment. I don't like to clutter up my home directory, so having a ~/tmp directory to put these things in keeps it clean and tidy.

You can, of course, save files in the system-wide temporary directory, /tmp, but that directory is cleared out periodically by the system, and if you are on a multi-user system, you might want to have a private temp directory anyway (all users normally have read and write access to /tmp). 

<<toBalaNotes "home">>


///%home
//%/
''參考文章''
1. Sudoers
https://help.ubuntu.com/community/Sudoers
2. Linux Users and Sudo
http://www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_:_Ch09_:_Linux_Users_and_Sudo

{{item1{sudo 的好處}}}
使用 su 變身為 root 執行程式時, 如果有人使用 Ctrl+C  中斷程式, 他就取得了 root 的權限, 而使用 sudo,只有該程式的執行使用 root 一旦結束或中斷,又變回低權限使用者比較安全

{{item1{sudo 命令實作}}}
{{{
cloudwalker@oncloud9:~$ sudo bash
[sudo] password for cloudwalker:                                (不是輸入 root 的密碼)
root@oncloud9:~#                                                (注意提示字串, 變成 root)

root@oncloud9:~# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin

root@oncloud9:~# echo $USER
root

root@oncloud9:~# echo $HOME
/home/cloudwalker                                                 (竟然還是 cloudwalker 的家目錄, 主要是執行 Script 時, 程式中的 $HOME 是代表目前登入使用者的家目錄, 而不是 root 的家目錄)

root@oncloud9:~# exit
exit
cloudwalker@oncloud9:~$
}}}

{{item1{使用者環境變數處理}}}

''1. 使用 -i 參數, 再次執行 sudo 命令''
{{{
cloudwalker@oncloud9:~$ sudo -i bash
root@oncloud9:~# echo $HOME                               (HOME 環境變數, 改成 /root)
/root
root@oncloud9:~# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
root@oncloud9:~# exit                                              (離開 sudo)
exit
cloudwalker@oncloud9:~$ echo $PATH
/home/cloudwalker/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
cloudwalker@oncloud9:~$ echo $HOME                   (HOME 環境變數, 變回原來使用者家目錄)
/home/cloudwalker
}}}

''-i 參數說明''
{{{
-i [command]
   The -i (simulate initial login) option runs the shell
   specified in the passwd(5) entry of the target user as a
   login shell.  This means that login-specific resource files
   such as .profile or .login will be read by the shell.  If a
   command is specified, it is passed to the shell for
   execution.  Otherwise, an interactive shell is executed.
   sudo attempts to change to that user's home directory
   before running the shell.  It also initializes the
   environment, leaving DISPLAY and TERM unchanged, setting
   HOME, SHELL, USER, LOGNAME, and PATH, as well as the
   contents of /etc/environment on Linux and AIX systems.  All
   other environment variables are removed.

   -i 會將這幾個 HOME, SHELL, USER, LOGNAME, PATH 環境變數, 重新設定
}}}

''2. 使用 -E 參數, 再次執行 sudo 命令''
-E 參數, 會保留使用者環境變數
{{{
cloudwalker@oncloud9:~$ sudo -E bash                          
root@oncloud9:~# env
SHELL=/bin/bash
TERM=xterm
XDG_SESSION_COOKIE=6d1e6dfd7d46d9bf4836bdd74c5932fe-1281752690.614263-230780165
SSH_CLIENT=192.168.56.1 1422 22
SSH_TTY=/dev/pts/0
USER=root
LS_COLORS=rs=0:di=01;34:ln=01;36:hl=44;37:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;  
                                                :
                                                :
SUDO_USER=cloudwalker
SUDO_UID=1000
USERNAME=root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin
MAIL=/var/mail/cloudwalker
PWD=/home/cloudwalker
LANG=zh_TW.UTF-8
SUDO_COMMAND=/bin/bash
HOME=/home/cloudwalker
SHLVL=2
LANGUAGE=zh_TW:zh
LOGNAME=root
SSH_CONNECTION=192.168.56.1 1422 192.168.56.128 22
LESSOPEN=| /usr/bin/lesspipe %s
SUDO_GID=1000
LESSCLOSE=/usr/bin/lesspipe %s %s
_=/usr/bin/env
}}}

''沒有保留使用者環境變數''
{{{
cloudwalker@oncloud9:~$ sudo bash
root@oncloud9:~# env
SHELL=/bin/bash
TERM=xterm
USER=root
LS_COLORS=rs=0:di=01;34:ln=01;36:hl=44;37:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:
                                                       :
                                                       :
SUDO_USER=cloudwalker
SUDO_UID=1000
USERNAME=root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin
MAIL=/var/mail/cloudwalker
PWD=/home/cloudwalker
LANG=en_US.UTF-8
SHLVL=1
SUDO_COMMAND=/bin/bash
HOME=/home/cloudwalker
LANGUAGE=en_US
LOGNAME=root
LESSOPEN=| /usr/bin/lesspipe %s
SUDO_GID=1000
LESSCLOSE=/usr/bin/lesspipe %s %s
_=/usr/bin/env
}}}

''問題 : 那些環境變數有保留 ?''

{{item1{使用其他使用者身份執行命令}}}
To list the home directory of user a001 on a machine where the filesystem holding ~a001 is not exported as root:
{{{
cloudwalker@oncloud9:~$ sudo -u a001 ls -al ~a001
總計 20
drwxr-xr-x 2 a001 a001 4096 2010-08-10 22:51 .
drwxr-xr-x 6 root root 4096 2010-08-10 22:51 ..
-rw-r--r-- 1 a001 a001  220 2010-04-19 09:51 .bash_logout
-rw-r--r-- 1 a001 a001 3103 2010-04-19 09:51 .bashrc
-rw-r--r-- 1 a001 a001  675 2010-04-19 09:51 .profile
}}}

{{item1{取消輸入密碼}}}
''$ sudo nano /etc/sudoers''
{{{
                 :
# User alias specification
# Cmnd alias specification
# User privilege specification
root    ALL=(ALL) ALL

# Allow members of group sudo to execute any command after they have
# provided their password
# (Note that later entries override this, so you might need to move
# it further down)
%sudo ALL=(ALL) ALL                                
#
#includedir /etc/sudoers.d

# Members of the admin group may gain root privileges
# admin 群組不論來自 [哪部主機] 登入,他可以[ 變換身份成為任何人] ,且可以進行系統上面的 [任何指令] 之意

%admin ALL=(ALL) NOPASSWD:ALL          # 不需再在輸入密碼
}}}

下式意思是,使用者 root 能從所有的終端機,以任何所有使用者的身分,來執行所有任何的指令。

''root    ALL=(ALL) ALL''

''修改內容如下圖''

[img[img/linux/sudolimit.png]]

''[註]'' Ubuntu 系統安裝時, 所產生的帳號, 會自動加入 admin 這群組


{{item1{限制可執行的命令 (1)}}}
{{op1{1. 修改 /etc/sudoers}}}
限定 xman01 及 xman02 這二個帳號, 只可利用 sudo 命令, 執行 /opt/lampp/lampp 這命令, 不可利用 sudo 執行其他命令

[img[img/linux/sudolimit1.png]]

{{op1{2. 測試功能}}}
''建立 xman01 帳號''
{{{
$ sudo useradd  -m  -s /bin/bash xman01
$ sudo passwd xman01
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
}}}

''切換身份為 xman01''
{{{
$ su - xman01
Password:
xman01@ubuntu:~$
}}}

''執行命令''
{{{
xman01@ubuntu:~$ sudo /opt/lampp/lampp start
[sudo] password for xman01:
Starting XAMPP for Linux 1.7.2...
XAMPP: Starting Apache with SSL (and PHP5)...
XAMPP: Starting MySQL...
XAMPP: Starting ProFTPD...
XAMPP for Linux started.

xman01@ubuntu:~$ sudo nano /etc/network/interfaces
Sorry, user xman01 is not allowed to execute '/usr/bin/nano /etc/network/interfaces' as root on ubuntu.localdomain.
}}}

{{item1{限制可執行的命令 (2)}}}
{{{
User_Alias  SOFTWAREMAINTAINERS = swift, john, danny
User_Alias  PASSWORDMAINTAINERS = swift, sysop
Cmnd_Alias  SOFTWARECOMMANDS    = /usr/bin/apt-get update, !/usr/bin/apt-get upgrade
Cmnd_Alias  PASSWORDCOMMANDS    = /usr/bin/passwd [a-zA-Z0-9_-]*, !/usr/bin/passwd root

SOFTWAREMAINTAINERS  localhost = SOFTWARECOMMANDS
PASSWORDMAINTAINERS  localhost = PASSWORDCOMMANDS
}}}

<<toBalaNotes "3">>


///%3
//%/
{{item1{重導 (>, <)}}}
{{{
資料流重新導向 (redirect) 由字面上的意思來看,就是將資料傳導到其他的檔案或裝置. 

Command  &>filename       (redirect both the stdout and the stderr of command to filename)

Command  >&2                (redirect stdout of command to stderr)
}}}

''Example''
{{{
root@oncloud9:~# ls -zzzz
ls: invalid option -- 'z'
請嘗試執行『ls --help』來獲取更多資訊。

root@oncloud9:~# ls -zzzz 2>test
root@oncloud9:~# cat test
ls: invalid option -- 'z'
請嘗試執行『ls --help』來獲取更多資訊。

root@oncloud9:~# ls -zzzz 2>/dev/null
root@oncloud9:~# cat /dev/null
}}}

''[註]'' /dev/null 是一個不執行任何動作的裝置

<<toBalaNotes "redirect">>

{{item1{導管 ( | )}}}
{{{
多個命令以接力方式, 處理文字資料, 以得到你所需的結果
}}}

''範例 1''
{{{
$ ls  -al  |  grep  file1

$ dpkg -l | grep nano    (顯示 nano 套件)
ii  nano           2.0.9-2           free curses-based text editor, inspired by P

$ ifconfig  | grep  eth
}}}

''範例 2''
{{{
$ echo abc>a01.lst
$ echo xyz>>a01.lst
$ cat a01.lst
abc
xyz
$ echo zzz>a02.lst
$ echo 123>>a02.lst

$ cat a02.lst
zzz
$ echo c123>>a02.lst
$ cat a02.lst
zzz
c123
$ cat *.lst | sort | uniq
abc
c123
xyz
zzz
}}}

''範例 3 : 底線換成空白''
{{{
x=A_B_C_D
# replace _ with a space
x=$(echo $x  |  sed 's/_/ /g')
echo $x
}}}

''You can create two aliases as follows to list only directories and files.''
{{{
alias lf="ls -l | egrep -v '^d'"
alias ldir="ls -l | egrep '^d'"
}}}
<<toBalaNotes "pipeline">>


///%redirect
//%/

///%pipeline
//%/
''參考文章''
1. Log file basics
http://www.ibm.com/developerworks/aix/library/au-satlogfilebasics/
{{item1{掛載光碟 (Ubuntu Server)}}}

''1. 產生掛載目錄''
{{{
$ sudo mkdir /media/cdrom
}}}

''2. 掛載光碟''
{{{
$ sudo mount -t iso9660 /dev/cdrom /media/cdrom
mount: block device /dev/sr0 is write-protected, mounting read-only
}}}

''3. 檢視掛載資訊''
{{{
$ df
檔案系統           1K-區段      已用     可用 已用% 掛載點
/dev/sda1             50136788   1525348  46064600   4% /
none                    250252       164    250088   1% /dev
none                    254452         0    254452   0% /dev/shm
none                    254452       256    254196   1% /var/run
none                    254452         0    254452   0% /var/lock
none                    254452         0    254452   0% /lib/init/rw
/dev/sr0                683998    683998         0 100% /media/cdrom
}}}

''4. 檢視光碟內容''
{{{
$ ls -al /media/cdrom
總計 169
dr-xr-xr-x 10 root root   2048 2010-04-27 18:57 .
drwxr-xr-x  4 root root   4096 2010-08-10 00:27 ..
-r-xr-xr-x  1 root root   1115 2010-04-24 10:29 cdromupgrade
dr-xr-xr-x  2 root root   2048 2010-04-27 18:57 .disk
dr-xr-xr-x  3 root root   2048 2010-04-27 18:56 dists
dr-xr-xr-x  3 root root   2048 2010-04-27 18:56 doc
dr-xr-xr-x  3 root root   2048 2010-04-27 18:57 install
dr-xr-xr-x  2 root root  16384 2010-04-27 18:57 isolinux
-r--r--r--  1 root root 133134 2010-04-27 18:57 md5sum.txt
dr-xr-xr-x  2 root root   2048 2010-04-27 18:56 pics
dr-xr-xr-x  3 root root   2048 2010-04-27 18:57 pool
dr-xr-xr-x  2 root root   2048 2010-04-27 18:56 preseed
-r--r--r--  1 root root    232 2010-04-27 18:56 README.diskdefines
lr-xr-xr-x  1 root root      1 2010-04-27 18:56 ubuntu -> .
}}}

{{item1{掛載硬碟}}}
''參考文章''
1. Linux / Unix Command: mkfs.vfat
http://linux.about.com/od/embedded/l/blcmdl8_mkfsvfa.htm

''1. 列出區塊裝置 (包含硬碟)''
{{{
$ ls /sys/block
fd0    loop2  loop5  ram0   ram11  ram14  ram3  ram6  ram9  sr0
loop0  loop3  loop6  ram1   ram12  ram15  ram4  ram7  sda
loop1  loop4  loop7  ram10  ram13  ram2   ram5  ram8  sdb
}}}

''2. 確認硬碟''
從以下命令, 得知硬碟大小
{{{
$ sudo fdisk -l /dev/sdb
Disk /dev/sda: 1073 MB, 1073741824 bytes
                   :
}}}

''@@color:red;[註]@@'' 如是新增 IDE 硬碟, 名稱編碼會在 SCSI 硬碟前面,例如, 二個 IDE 硬碟, 一個 SCSI 硬碟, IDE 名稱為 sda, sdb, 而 SCSI 硬碟為 sdc

''2. 硬碟分割''
{{{
$ sudo fdisk /dev/sdb
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel with disk identifier 0x797b64c4.
Changes will remain in memory only, until you decide to write them.
After that, of course, the previous content won't be recoverable.

Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
         switch off the mode (command 'c') and change display units to
         sectors (command 'u').

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-130, default 1):
Using default value 1
Last cylinder, +cylinders or +size{K,M,G} (1-130, default 130):
Using default value 130

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.
}}}

''3. 格式化硬碟''
{{{
$ sudo mkfs.vfat /dev/sdb1
mkfs.vfat 3.0.7 (24 Dec 2009)
}}}

''4. 掛載硬碟''
{{{
$ mkdir dos
$ sudo mount -t vfat /dev/sdb1 dos
$ ls -al dos
總計 8
drwxr-xr-x 2 root        root        4096 1970-01-01 08:00 .
drwxr-xr-x 3 cloudwalker cloudwalker 4096 2010-08-10 23:29 ..
}}}

''5. 顯示所有掛載裝置資訊''
{{{
cloudwalker@oncloud9:~/dos$ mount
/dev/sda1 on / type ext4 (rw,errors=remount-ro)
proc on /proc type proc (rw,noexec,nosuid,nodev)
none on /sys type sysfs (rw,noexec,nosuid,nodev)
none on /sys/fs/fuse/connections type fusectl (rw)
none on /sys/kernel/debug type debugfs (rw)
none on /sys/kernel/security type securityfs (rw)
none on /dev type devtmpfs (rw,mode=0755)
none on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=0620)
none on /dev/shm type tmpfs (rw,nosuid,nodev)
none on /var/run type tmpfs (rw,nosuid,mode=0755)
none on /var/lock type tmpfs (rw,noexec,nosuid,nodev)
none on /lib/init/rw type tmpfs (rw,nosuid,mode=0755)
/dev/sdb1 on /home/cloudwalker/dos type vfat (rw)              (/dev/sdb1 的掛載資訊)
}}}

''使用掛載裝置''
{{{
$ ls -al dos               (還沒掛載任何裝置)
總計 8
drwxr-xr-x 2 student student 4096 2010-09-23 22:34 .
drwxr-xr-x 9 student student 4096 2010-09-23 22:34 ..

$ mount -t vfat /dev/sdb1 dos     
mount: only root can do that
$ sudo mount -t vfat /dev/sdb1 dos    (掛載 /dev/sdb1 裝置)

$ ls -al dos
總計 8
drwxr-xr-x 2 root    root    4096 1970-01-01 08:00 .              (此時 dos 此目錄的權限設定 755, 只有 root 這 owner 可建立檔案)
drwxr-xr-x 9 student student 4096 2010-09-23 22:34 ..

$ touch dos/student.txt
touch: 無法觸碰(touch)「dos/student.txt」: 拒絕不符權限的操作

$ sudo chmod 777 dos
$ ls -al dos
總計 8
drwxr-xr-x 2 root    root    4096 1970-01-01 08:00 .                    (目錄權限沒有被改變)
drwxr-xr-x 9 student student 4096 2010-09-23 22:34 ..

$ touch dos/student.txt
touch: 無法觸碰(touch)「dos/student.txt」: 拒絕不符權限的操作
}}}

<<toBalaNotes "mhd">>

{{item1{掛載權限設定}}}
''ntfs/vfat'' permissions are set at the time of mounting the partition with ''umask'', ''dmask'', and ''fmask'' and can not be changed with commands such as ''chown'' or ''chmod''.

I advise dmask=027,fmask=137 (if you user umask=000 all your files will be executable). More permissive options would be dmask=000,fmask=111. 

以下命令掛載時, other 的權限為 read (umask=003), 以至無法執行 ls 命令 (無法進入目錄 (cd), 當然就無法列出檔案清單 (ls)
{{{
cloudwalker@oncloud9:~$ sudo mount -t vfat -o iocharset=utf8,umask=003 /dev/sdb1 dos
cloudwalker@oncloud9:~$ ls -al dos
ls: 無法存取dos/.: 拒絕不符權限的操作
ls: 無法存取dos/..: 拒絕不符權限的操作
ls: 無法存取dos/zzz: 拒絕不符權限的操作
總計 0
d????????? ? ? ? ?                ? .
d????????? ? ? ? ?                ? ..
d????????? ? ? ? ?                ? zzz
}}}

''重新掛載, other 權限為 read,write,exec (umask=000)''
{{{
cloudwalker@oncloud9:~$ sudo umount dos
cloudwalker@oncloud9:~$ sudo mount -t vfat -o iocharset=utf8,umask=000 /dev/sdb1 dos
cloudwalker@oncloud9:~$ ls -al dos
總計 12
drwxrwxrwx 3 root        root        4096 1970-01-01 08:00 .
drwxr-xr-x 8 cloudwalker cloudwalker 4096 2010-08-18 22:34 ..
drwxrwxrwx 2 root        root        4096 2010-08-18 22:35 zzz
}}}

{{item1{設定掛載編碼}}}
{{{
cloudwalker@oncloud9:~$ sudo umount dos
cloudwalker@oncloud9:~$ sudo mount -t vfat -o iocharset=utf8 /dev/sdb1 dos
cloudwalker@oncloud9:~$ ls -al dos
總計 12
drwxr-xr-x 3 root        root        4096 1970-01-01 08:00 .
drwxr-xr-x 8 cloudwalker cloudwalker 4096 2010-08-18 22:34 ..
drwxr-xr-x 2 root        root        4096 2010-08-18 22:35 zzz
}}}

{{item1{ext3 掛載限制}}}
ext3 不能用 gid,umask 這個參數,由 man mount 這命令, 就可以看到, 解決方式如下 :

1. 先 mount 好之後,比如 mount -t ext3 /dev/hda4 /mnt/linux 之後

2. 再用 chgrp 1002 /mnt/linux ; chmod 774 /mnt/linux

{{item1{自動掛載 USB 儲存裝置}}}
''參考文章''
1. How to automount USB drive on Ubuntu Server 10.04
http://www.pvnilsson.com/2010/08/06/how-to-automount-usb-drive-on-ubuntu-server-10-04/

If you want an external USB drive to be mounted when you plug it into your server then you will need the usbmount service to be installed since its not a part of the Ubuntu Server 10.04 LTS default setup.

{{op1{安裝 usbmount}}}

''1. open a linux terminal and change user to root''

''2. 安裝 BIG5''
{{{
$ sudo locale-gen zh_TW
Generating locales...
  zh_TW.BIG5... done
Generation complete.
}}}

''3. type this command:''
{{{
$ sudo apt-get install usbmount
正在讀取套件清單... 完成
正在重建相依關係
正在讀取狀態資料... 完成
下列的額外套件將被安裝:
  libhal-storage1 libhal1 pmount
建議套件:
  hal cryptsetup
下列【新】套件將會被安裝:
  libhal-storage1 libhal1 pmount usbmount
升級 0 個,新安裝 4 個,移除 0 個,有 1 個未被升級。
需要下載 257kB 的套件檔。
此操作完成之後,會多佔用 1,417kB 的磁碟空間。
是否繼續進行 [Y/n]?
}}}

Its now ready to go and your USB drive will be mounted on ''/media/usb0'' when a drive is plugged into a usb port.

{{op1{使用掛載 USB}}}

''1. 移除原先掛載''
{{{
$ sudo umount /media/usb0                                    
}}}

''2. 重新掛載''
{{{
$ sudo mount -t vfat -o iocharset=utf8,umask=003 /dev/sdc1 /media/usb0
}}}

''3. 開始使用''
{{{
student@US1041OC9:~$ ls -al /media/usb0                          (因 student 這帳號, 無法進入 /media/usb0 這目錄)
ls: 無法存取/media/usb0/.: 拒絕不符權限的操作
ls: 無法存取/media/usb0/..: 拒絕不符權限的操作
ls: 無法存取/media/usb0/KVMZIP: 拒絕不符權限的操作
ls: 無法存取/media/usb0/201008-文化網工-中型企業網路建置: 拒絕不符權限的操作
ls: 無法存取/media/usb0/ubuntu-10.04.1-server-amd64.iso: 拒絕不符權限的操作
ls: 無法存取/media/usb0/CW2K3wSP1NOCDKey.ISO: 拒絕不符權限的操作
總計 0
d????????? ? ? ? ?                ? .
d????????? ? ? ? ?                ? ..
d????????? ? ? ? ?                ? 201008-文化網工-中型企業網路建置
-????????? ? ? ? ?                ? CW2K3wSP1NOCDKey.ISO
d????????? ? ? ? ?                ? KVMZIP
-????????? ? ? ? ?                ? ubuntu-10.04.1-server-amd64.iso


student@US1041OC9:~$ sudo ls -al /media/usb0
總計 1326308
drwxrwxr--  4 root root      8192 1970-01-01 08:00 .
drwxr-xr-x 11 root root      4096 2010-09-23 21:31 ..
drwxrwxr--  2 root root      8192 2010-08-27 08:38 201008-文化網工-中型企業網路建置
-rwxrwxr--  1 root root 642465792 2008-03-12 10:08 CW2K3wSP1NOCDKey.ISO
drwxrwxr--  2 root root      8192 2010-08-27 10:12 KVMZIP
-rwxrwxr--  1 root root 715644928 2010-09-03 18:32 ubuntu-10.04.1-server-amd64.iso

student@US1041OC9:~$ sudo touch /media/usb0/aaa.txt                (使用 root 帳號, 產生 aaa.txt 這個檔案)
student@US1041OC9:~$ sudo ls -al /media/usb0
總計 1326308
drwxrwxr--  4 root root      8192 2010-09-23 22:09 .
drwxr-xr-x 11 root root      4096 2010-09-23 21:31 ..
drwxrwxr--  2 root root      8192 2010-08-27 08:38 201008-文化網工-中型企業網路建置
-rwxrwxr--  1 root root         0 2010-09-23 22:09 aaa.txt
-rwxrwxr--  1 root root 642465792 2008-03-12 10:08 CW2K3wSP1NOCDKey.ISO
drwxrwxr--  2 root root      8192 2010-08-27 10:12 KVMZIP
-rwxrwxr--  1 root root 715644928 2010-09-03 18:32 ubuntu-10.04.1-server-amd64.iso
}}}

{{op1{Configure mount point}}}
If you want the first usb drive to be mounted on a different mountpoint like ''/backup''

''1. create the directory where you want your drive to be mounted into.''
{{{
mkdir /backup
}}}

''2. edit /etc/usbmount/usbmount.conf and add the /backup to MOUNTPOINTS:''
{{{
MOUNTPOINTS="/media/usb0 /media/usb1 /media/usb2 /media/usb3
/media/usb4 /media/usb5 /media/usb6 /media/usb7"
}}}
To:
{{{
MOUNTPOINTS="/backup /media/usb0 /media/usb1 /media/usb2 /media/usb3
/media/usb4 /media/usb5 /media/usb6 /media/usb7"
}}}

{{item1{How to mount Samba (SMB) drives automatically during boot in Ubuntu 10.04 Lucid Lynx}}}
http://blog.homelinux.org/?p=63

<<toBalaNotes "mount">>

///%mount
//%/

///%mhd
//%/
''參考文章''
1. What is SGID and how to set SGID in Linux?
http://www.linuxnix.com/2011/12/sgid-set-sgid-linuxunix.html

{{item1{Sticky Bit}}}
這個 Sticky Bit, SBIT 目前只針對目錄有效,對於檔案已經沒有效果了。 SBIT 對於目錄的作用是:
{{{
* 當使用者對於此目錄具有 w, x 權限,亦即具有寫入的權限時;
* 當使用者在該目錄下建立檔案或目錄時,僅有自己與 root 才有權力刪除該檔案
}}}
換句話說:當甲這個使用者於 A 目錄是具有群組或其他人的身份,並且擁有該目錄 w 的權限, 這表示『甲使用者對該目錄內任何人建立的目錄或檔案均可進行 "刪除/更名/搬移" 等動作。』 不過,如果將 A 目錄加上了 SBIT 的權限項目時, 則甲只能夠針對自己建立的檔案或目錄進行刪除/更名/移動等動作,而無法刪除他人的檔案。

{{op1{/tmp 目錄實作}}}

''1. 檢視 /tmp 目錄權限''
{{{
$ stat /tmp
  File: 「/tmp」
  Size: 4096            Blocks: 8          IO Block: 4096   目錄
Device: 801h/2049d      Inode: 380         Links: 2
Access: (1777/drwxrwxrwt)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2010-10-27 00:44:54.995737336 +0800
Modify: 2010-10-11 23:10:45.902201242 +0800
Change: 2010-10-11 23:10:45.902201242 +0800
}}}

''2. 檔案操作''
{{{
$ touch /tmp/student.txt
$ ll /tmp
總計 8
drwxrwxrwt  2 root    root    4096 2010-10-27 00:51 ./
drwxr-xr-x 22 root    root    4096 2010-09-19 18:59 ../
-rw-r--r--  1 student student    0 2010-10-27 00:51 student.txt

student@US1041OC9:~$ sudo useradd -m -s /bin/bash xman01            (產生 xman01 使用者)
student@US1041OC9:~$ sudo passwd xman01
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully

student@US1041OC9:~$ su xman01                                                   (切換為 xman01)
密碼:
Added user xman01.

xman01@US1041OC9:/home/student$ rm /tmp/student.txt                     (刪除 student 帳號產生的檔案, 不會成功)
rm:是否移除有防寫保護的 普通空白檔案 「/tmp/student.txt」? y
rm: 無法建立目錄「/tmp/student.txt」: 此項操作並不被允許


xman01@US1041OC9:/home/student$ touch /tmp/xman01.txt
xman01@US1041OC9:/home/student$
xman01@US1041OC9:/home/student$ exit
exit
student@US1041OC9:~$ rm /tmp/xman01.txt
rm:是否移除有防寫保護的 普通空白檔案 「/tmp/xman01.txt」? y
rm: 無法建立目錄「/tmp/xman01.txt」: 此項操作並不被允許
}}}
<<toBalaNotes "1">>

///%1
//%/
''參考文章''
2. Learn Linux, 101: Process execution priorities
http://www.ibm.com/developerworks/linux/library/l-lpic1-v3-103-6/index.html

''一般使用者帳號''可設定的優先順序範圍為 ''1~19'', 而 ''root'' 可設定的優先順序範圍為'' -20 ~ 19''. 一般使用者帳號只能改變自己行程的優先順序. ''優先順序值(PRI) 越高'', 執行的''優先順序越低'', 其公式如下: 
{{{
PRI(new) = PRI(old) + nice
}}}

''檢視內定 nice 值''
{{{
$ nice
0
}}}

<<toBalaNotes "1">>
{{item1{撰寫 CPU-intensive 測試程式}}}

''第一個參數'' 用來倒數, ''第二個參數'' 只是一個識別名稱
{{{
$ nano count1.sh 
#!/bin/bash

x="$1"
echo "$2" $(date)
while [ $x -gt 0 ]; do
x=$(( x-1 ))
done
echo "$2" $(date) 
}}}

''執行測試程式'' 
{{{
$ ./count1.sh 10000 A
A Wed Jan 20 08:34:16 EST 2010
A Wed Jan 20 08:34:16 EST 2010

$ ./count1.sh 99000 A
A Wed Jan 20 08:34:20 EST 2010
A Wed Jan 20 08:34:22 EST 2010
}}}

{{item1{檢視執行狀態}}}

只執行一個測試程式, 這時會佔用將近 100% 的 CPU 資源

''$ (./count1.sh 5000000 A&);top''
{{{
top - 00:37:21 up 11 min,  2 users,  load average: 0.22, 0.05, 0.02
Tasks:  64 total,   1 running,  63 sleeping,   0 stopped,   0 zombie
Cpu(s): 40.6%us,  0.0%sy,  0.0%ni, 59.1%id,  0.0%wa,  0.3%hi,  0.0%si,  0.0%st
top - 00:38:02 up 11 min,  2 users,  load average: 0.33, 0.09, 0.03
Tasks:  65 total,   2 running,  63 sleeping,   0 stopped,   0 zombie
Cpu(s): 97.4%us,  2.3%sy,  0.0%ni,  0.0%id,  0.0%wa,  0.3%hi,  0.0%si,  0.0%st
Mem:    250332k total,    72620k used,   177712k free,    27116k buffers
Swap:   139256k total,        0k used,   139256k free,    26904k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND            
  892 student   20   0  4208 1312 1128 R 99.9  0.5   0:18.63 count1.sh          
  893 student   20   0  2416 1136  904 R  0.7  0.5   0:00.10 top                
    1 root      20   0  2656 1584 1188 S  0.0  0.6   0:00.20 init               
    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd           
    3 root      RT   0     0    0    0 S  0.0  0.0   0:00.00 migration/0        
    4 root      20   0     0    0    0 S  0.0  0.0   0:00.00 ksoftirqd/0        
    5 root      RT   0     0    0    0 S  0.0  0.0   0:00.00 watchdog/0         
    6 root      20   0     0    0    0 S  0.0  0.0   0:00.24 events/0            
}}}

''[問題]'' 如同時執行三個測試程式, CPU 資源如何分配 ?

<<toBalaNotes "1">>
{{item1{程序優先順序 (nice)}}}

''$ (./count1.sh 2000000 A&);(nice -n 19 ./count1.sh 2000000 B&);sleep 3;ps -l;sleep 60''
{{{
A Tue Oct 12 00:56:47 CST 2010
B Tue Oct 12 00:56:47 CST 2010
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S  1000   846   699  0  80   0 -  1787 wait   ttyS0    00:00:00 bash
0 R  1000   959     1 99  80   0 -  1052 -      ttyS0    00:00:02 count1.sh
0 R  1000   961     1  1  99  19 -  1052 -      ttyS0    00:00:00 count1.sh
0 R  1000   965   846  0  80   0 -   626 -      ttyS0    00:00:00 ps
A Tue Oct 12 00:57:17 CST 2010
B Tue Oct 12 00:57:47 CST 2010                                                     (比 A 多 30 秒)
}}}

{{item1{調整程序優先順序 (renice)}}}
{{{
$ ./count1.sh 10000000 A&
[1] 985
$ A Tue Oct 12 01:12:59 CST 2010

$ ps -l
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S  1000   846   699  0  80   0 -  1787 wait   ttyS0    00:00:00 bash
0 R  1000   985   846 99  80   0 -  1052 -      ttyS0    00:00:04 count1.sh
0 R  1000   987   846  0  80   0 -   626 -      ttyS0    00:00:00 ps

$ renice +3 985
985: old priority 0, new priority 3

$ ps -l
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S  1000   846   699  0  80   0 -  1787 wait   ttyS0    00:00:00 bash
0 R  1000   985   846 99  83   3 -  1052 -      ttyS0    00:00:51 count1.sh
0 R  1000   990   846  0  80   0 -   626 -      ttyS0    00:00:00 ps

$ renice -3 985
renice: 985: setpriority: Permission denied

$ sudo renice -3 985
985: old priority 3, new priority -3

$ ps -l
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S  1000   846   699  0  80   0 -  1787 wait   ttyS0    00:00:00 bash
0 R  1000   985   846 99  77  -3 -  1052 -      ttyS0    00:01:31 count1.sh
0 R  1000   994   846  0  80   0 -   626 -      ttyS0    00:00:00 ps
}}}

<<toBalaNotes "3">>

///%1
//%/

///%3
//%/
{{{
student@US104-100-NAT:~/bin$ cat sysprep.sh
#!/bin/bash
# Author : Sung-Lin Chen
# License : GPLv2

[ "$USER" != "root" ] && echo "need sudo" && exit 1
[ "$PWD" != "$HOME/bin" ] && echo "change to $HOME/bin" && exit 1

# logout flag
rlflag='0'
# reboot flag
rbflag='0'

grep 'alias ping=' "$HOME/.bashrc" &>/dev/null
if [ "$?" != "0" ]; then

   sudo locale-gen en_US.UTF-8 &>/dev/null
   [ "$?" == "0" ] && echo "locale (en_US) ok"

   cp "$HOME/bin/sample/.bashrc" "$HOME/.bashrc"
   echo ".bashrc ok"

   rlflag=1
fi

if [ ! -f /etc/init/ttyS0.conf ]; then
   cp "$HOME/bin/sample/ttyS0.conf" /etc/init/
   echo "ttyS0.conf ok"
   rbflag=1
fi

if [ "$rbflag" == "1" ];then
   read -p "reboot (y/n) " ans
   if [ "$ans" == "y" ]; then
      reboot
   fi
fi

if [ "$rlflag" == "1" ];then
   read -p "logout (y/n) " ans
   if [ "$ans" == "y" ]; then
      logout
   fi
fi

exit 0
}}}

<<toBalaNotes "1">>


///%1
//%/
''參考文章''
1. Making a GRUB boot floppy.
https://help.ubuntu.com/community/GrubHowto/BootFloppy

{{op1{1. 格式化 GRUB 開機片}}}
{{{
$ sudo mke2fs /dev/fd0
[sudo] password for cloudwalker:
mke2fs 1.41.11 (14-Mar-2010)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
184 inodes, 1440 blocks
72 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=1572864
1 block group
8192 blocks per group, 8192 fragments per group
184 inodes per group

Writing inode tables: done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 22 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
}}}

{{op1{2. 寫入 GRUB 開機片}}}
{{{
$ sudo mount /dev/fd0 /media/floppy
$ sudo mkdir /media/floppy/boot
$ sudo mkdir /media/floppy/boot/grub
$ cd /boot/grub
$ sudo cp stage1 stage2 menu.lst device.map e2fs_stage1_5  /media/floppy/boot/grub
}}}

{{op1{3. 設定 GRUB 開機片}}}
{{{
$ sudo umount /dev/fd0
$ sudo grub
       [ Minimal BASH-like line editing is supported.   For
         the   first   word,  TAB  lists  possible  command
         completions.  Anywhere else TAB lists the possible
         completions of a device/filename. ]

grub> device (fd0) /dev/fd0

grub> root (fd0)

grub> setup (fd0)
 Checking if "/boot/grub/stage1" exists... yes
 Checking if "/boot/grub/stage2" exists... yes
 Checking if "/boot/grub/e2fs_stage1_5" exists... yes
 Running "embed /boot/grub/e2fs_stage1_5 (fd0)"... failed (this is not fatal)
 Running "embed /boot/grub/e2fs_stage1_5 (fd0)"... failed (this is not fatal)
 Running "install /boot/grub/stage1 (fd0) /boot/grub/stage2 p /boot/grub/menu.l
st "... succeeded
Done.

grub> quit
}}}

{{op1{4. 修改開機選單}}}
將 timout 及 hiddenmenu 這二行註解, 如下圖 :

[img[img/ubuntu10.4/Server/setupgrubmenu.png]]

{{op1{5. 重新開機}}}
{{{
$ sudo reboot
}}}


{{item1{多重開機}}}
Ubuntu 6.06 及後面的版本在安裝過程中,若偵測到其他分割區有"認得"的作業系統,才會詢問「是否將 GRUB 安裝至 MBR 上?」, 否則將省略詢問步驟,逕自把 GRUB 的 MBR 覆蓋原先的 MBR 上.

''[註]'' 可使用安裝光碟的 "救援已損壞的系統" 選項, 來重建 GRUB

{{item1{Writing Grub to floppy during Ubuntu 9.10 install}}}
GRUB 2 is standard on Ubuntu starting with 9.10. During its installation from the Live CD, you can specify if you want GRUB 2 installed, and if so, where to put it. Here's how:

Start the Live CD installer.
Step: Disk Setup
"Specify Partitions Manually"
Step: Summary
Advanced button at lower right
Check or un-check to install GRUB 2 bootloader
Choose from the drop-down list where to install GRUB 2
sda = the MBR of drive sda
sda1 = the first partition of drive sda
sdb = the MBR of drive sdb
etc. 

{{item1{for 迴圈命令}}}

''1. 處理字串''
{{{
$ nano ipconfig.sh
for n in aaa bbb
do
  echo $n
done
}}}

''2. 檢查網卡''
{{{
$ nano ipconfig.sh
e=$(ifconfig -a)

for n in eth0 eth1
do
   echo "$e" | grep "$n" &>/dev/null
   [ "$?" == "0" ] && echo "$n 存在"
done
}}}

''3. 檢視目錄清單''
{{{
$ nano  mydir.sh
for  myfile  in  /etc/r*
do
      if  [  -d  “$myfile”  ]
      then
           echo  “$myfile  (dir)”
      else
           echo  “$myfile”
      fi
done
}}}

''4. 顯示文字檔內容''
{{{
#!/bin/bash

ip=$(cat ip.txt)

for i in "$ip"
do
  echo "$i"
done
}}}

''ip.txt 檔案內容''
{{{
$ cat ip.txt
172.30.33.1
192.168.1.1
}}}

<<toBalaNotes "1">>

{{item1{while 迴圈命令}}}

''1. 顯示 0 到 9 的數字''
{{{
$  nano  mywhile.sh
myvar=0
while [  $myvar  -ne  10  ]
do
    echo  $myvar
    myvar=$(( $myvar + 1 ))
done
}}}

''2. IP Scan 程式設計''
{{{
#!/bin/bash
c=10
while [ $c -ne 20 ]
do 
   echo -n 140.137.217."$c"
   ping -c 1 140.137.217."$c" &>/dev/null
   if [ "$?" == "0" ]; then
     echo ok
   else
     echo
   fi
   c=$(( $c+1 ))
done
}}}

''[註]'' 使用 fping 命令, 可以輕易執行網路 IP 檢查, 命令如下 :
{{{
$ fping -c 1 -q -g 140.137.214.0./24
}}}

<<toBalaNotes "2">>


///%1
//%/

///%2
//%/
''參考文章''
1. Speeding up your Updates with Ubuntu and APT Cacher NG (必讀)
http://opencomputing.blogspot.com/2010/07/speeding-up-your-updates-with-ubuntu.html
2. How to install and configure Apt-Cacher NG on Ubuntu Server 10.04
http://acidborg.wordpress.com/2010/06/24/how-to-install-and-configure-apt-cacher-ng-on-ubuntu-server-10-04/
3. Apt-Cacher-NG User Manual
http://www.unix-ag.uni-kl.de/~bloch/acng/html/index.html

Description: ''Apt-Cacher NG''  is a caching proxy specialized for package files from GNU/Linux distributors, primarily for Debian and Debian based distributions (like Ubuntu). This means that if you have many Debian/Ubuntu machines on your network, you just have to download the deb packages (new software, updates, distro upgrades, etc) from the internet once and the rest of the Debian/Ubuntu machines get them from Apt-Cacher NG cache, saving time and internet bandwidth. To install it, follow these simple steps:
Steps:
{{{
1. Installation: apt-get install apt-cacher-ng

2. Configuration: Edit /etc/apt-cacher-ng/acng.conf with the following content:
    CacheDir: /var/cache/apt-cacher-ng
    LogDir: /var/log/apt-cacher-ng
    Port:9999
    BindAddress: 0.0.0.0
    Remap-debrep: file:deb_mirror*.gz /debian ; file:backends_debian
    Remap-uburep: file:ubuntu_mirrors /ubuntu ; file:backends_ubuntu
    PidFile: /var/run/apt-cacher-ng/pid
    ExTreshold: 4

3. Restart Apt-Cacher NG: /etc/init.d/apt-cacher-ng restart

4. Create on the rest of the Debian/Ubuntu machines on the network the file /etc/apt/apt.conf.d/02proxy with the following content:

    Acquire::http { Proxy "http://your-apt-cacher-ng-server:3142"; };
}}}
Next time any of your machines needs a deb package, it will ask Apt-Cacher NG for it. If this package was asked previously by any of the other machines, Apt-Cacher will have a copy and will deliver it. Otherwise, it will fetch it from the internet repositories, keep a local copy and deliver it.

''sudo apt-get clean''

This will clean the system cache of installed packages out of ''/var/cache/apt'', saving some disk space. This is generally a good idea to do on any Ubuntu system with disk space limitations, whether or not you are running apt-cacher-ng.

Also, if you ever need to delete the files under ''/var/cache/apt-cacher-ng'', you may safely do so, and apt-cacher will download them again the next time they are needed.

{{item1{檢視快取狀態}}}

''1. 連接以下網址''
{{{
http://140.137.214.125:9999/acng-report.html
}}}

[img[img/linux/aptcache01.png]]
<<toBalaNotes "1">>


///%1
//%/
You should never use normal sudo to start graphical applications as root. You should use gksudo (kdesudo on Kubuntu) to run such programs. gksudo sets HOME=~root, and copies .Xauthority to a tmp directory. This prevents files in your home directory becoming owned by root. (AFAICT, this is all that's special about the environment of the started process with gksudo vs. sudo).

''Examples:''
{{{
gksudo gedit /etc/fstab
}}}
or
{{{
kdesudo kate /etc/X11/xorg.conf
}}}
* To run the graphical configuration utilities, simply launch the application via the Administration menu.
* gksudo and kdesudo simply link to the commands gksu and kdesu

{{item1{Add Nautilus superuser shortcut to the menubar}}}

[img[img/Gksudo-Menubar.png]]
Linux users: Since you spend most of your time fishing around the file system moving and editing files, reader Joe writes in with a time-saving shortcut he uses in Ubuntu.

Add sudo nautilus to the panel (menu) in Ubuntu to quickly launch Ubuntu's file explorer as a superuser. This is useful if you wish to edit files in folders which have restrictive permissions.

Obviously, Joe's tip is not specific to Ubuntu. As I've always understood it, you should use gksudo instead of sudo when requesting superuser privileges outside of the terminal. Anyone know how to change the default Gnome menu entry for "Computer" to call gksudo 
<<toBalaNotes "gsudo">>

///%gsudo
//%/

''參考文章''
1. Parallelize applications for faster Linux booting
http://www.ibm.com/developerworks/library/l-boot-faster/
2. Ubuntu's Success Story: the Upstart Startup Manager (Linux Boot Camp p.2)
http://www.linuxplanet.com/linuxplanet/print/7033

{{item1{認識 Upstart}}}
''Upstart 官方網站'' : http://upstart.ubuntu.com/index.html

''Upstart'' is an ''event-based'' replacement for the ''/sbin/init'' daemon which handles starting of tasks and services during boot, stopping them during shutdown and supervising them while the system is running.

It was originally developed for the Ubuntu distribution, but is intended to be suitable for deployment in all Linux distributions as a replacement for the venerable ''System-V init''. 

{{op1{1. 列出開機程序檔}}}
{{{
$ ls -al /etc/init
總計 136
drwxr-xr-x  2 root root 4096 2009-11-26 20:20 .
drwxr-xr-x 74 root root 4096 2009-11-28 13:07 ..
-rw-r--r--  1 root root  261 2009-09-15 21:09 atd.conf
-rw-r--r--  1 root root  356 2009-10-16 03:18 control-alt-delete.conf
-rw-r--r--  1 root root  297 2009-09-15 21:12 cron.conf
-rw-r--r--  1 root root  273 2009-10-15 12:27 dmesg.conf
-rw-r--r--  1 root root  312 2009-09-10 21:16 hostname.conf
-rw-r--r--  1 root root  557 2009-10-23 05:51 hwclock.conf
-rw-r--r--  1 root root  444 2009-10-23 05:51 hwclock-save.conf
-rw-r--r--  1 root root  367 2009-09-16 05:46 module-init-tools.conf
-rw-r--r--  1 root root  793 2009-10-26 18:59 mountall.conf
-rw-r--r--  1 root root  335 2009-10-26 18:59 mountall-net.conf
-rw-r--r--  1 root root  261 2009-10-26 18:59 mountall-reboot.conf
-rw-r--r--  1 root root 1073 2009-10-26 18:59 mountall-shell.conf
-rw-r--r--  1 root root  290 2009-09-15 05:06 networking.conf
-rw-r--r--  1 root root  493 2009-09-15 04:56 network-interface.conf
-rw-r--r--  1 root root  293 2009-09-16 05:46 procps.conf
-rw-r--r--  1 root root  354 2009-10-16 03:18 rc.conf
-rw-r--r--  1 root root  822 2009-10-16 03:18 rcS.conf
-rw-r--r--  1 root root 1453 2009-10-16 03:18 rc-sysinit.conf
-rw-r--r--  1 root root  280 2009-10-15 12:27 rsyslog.conf
-rw-r--r--  1 root root  589 2009-10-15 12:27 rsyslog-kmsg.conf
-rw-r--r--  1 root root  228 2009-10-16 03:18 tty1.conf
-rw-r--r--  1 root root  213 2009-10-16 03:18 tty2.conf
-rw-r--r--  1 root root  213 2009-10-16 03:18 tty3.conf
-rw-r--r--  1 root root  213 2009-10-16 03:18 tty4.conf
-rw-r--r--  1 root root  213 2009-10-16 03:18 tty5.conf
-rw-r--r--  1 root root  213 2009-10-16 03:18 tty6.conf
-rw-r--r--  1 root root  316 2009-09-22 05:10 udev.conf
-rw-r--r--  1 root root  769 2009-09-22 05:10 udev-finish.conf
-rw-r--r--  1 root root  356 2009-09-22 05:10 udevmonitor.conf
-rw-r--r--  1 root root  318 2009-09-22 05:10 udevtrigger.conf
-rw-r--r--  1 root root  344 2009-09-24 08:41 ufw.conf
-rw-r--r--  1 root root  313 2009-10-16 03:18 upstart-udev-bridge.conf
}}}

''[注意]'' Ubuntu Linux 不再使用 ''/etc/event.d'' 了
包含在 Ubuntu 9.10 中的 upstart 版本不再使用 /etc/event.d 資料夾底下的設定檔,而以 /etc/init 資料夾取而代之。([[402759|https://bugs.launchpad.net/ubuntu/+source/upstart/+bug/402759]]) 

{{op1{2. 列出程序狀態資訊}}}
{{{
$ sudo initctl list
mountall-net stop/waiting
rc stop/waiting
rsyslog start/running, process 500
tty4 start/running, process 692
udev start/running, process 369
upstart-udev-bridge start/running, process 361
hwclock-save stop/waiting
tty5 start/running, process 694
atd start/running, process 711
control-alt-delete stop/waiting
hwclock stop/waiting
module-init-tools stop/waiting
cron start/running, process 710
mountall stop/waiting
rcS stop/waiting
ufw start/running
rc-sysinit stop/waiting
tty2 start/running, process 698
udevtrigger stop/waiting
rsyslog-kmsg start/running, process 450
tty3 start/running, process 699
udev-finish stop/waiting
hostname stop/waiting
mountall-reboot stop/waiting
mountall-shell stop/waiting
network-interface (lo) start/running
network-interface (eth0) start/running
tty1 start/running, process 798
udevmonitor stop/waiting
dmesg stop/waiting
networking stop/waiting
procps stop/waiting
tty6 start/running, process 701
}}}

<<toBalaNotes "1">>

{{item1{自定事件程序}}}
{{{
$ cat /etc/init/myjob.conf
start on hithere 
script 
	echo "Hi there, here I am!" > /tmp/myjob.out
 	date >> /tmp/myjob.out 
	end script


$ sudo initctl emit hithere
hithere
myjob (start) waiting
myjob (start) starting
myjob (start) pre-start
myjob (start) spawned, process 8436
myjob (start) post-start, (main) process 8436
myjob (start) running, process 8436
myjob (stop) running
myjob (stop) stopping
myjob (stop) killed
myjob (stop) post-stop
myjob (stop) waiting

$ cat /tmp/myjob.out 
Hi there, here I am! 
Sat Jul 7 20:19:13 PDT 2007 

$ sudo initctl list myjob 
myjob (stop) waiting
}}}

<<toBalaNotes "2">>

///%1
//%/

///%2
//%/
''1. 處理副檔名''
{{{
$  nano  mycase.sh
x=aaa.bz2
case  “${x##*.}”  in
     gz)
          echo hi gz
          ;;
     bz2)
         echo hi bz2
         ;;
     *)
         echo “Archive format not recognized.”
         exit
         ;;
esac
}}}

''2. 輸入判斷''
{{{
$ nano selectno.sh
#!/bin/bash
clear

read -p "Enter NO " n

case  "$n"  in
     "1")
          clear
          ;;
     "2")
         uname -r
         ;;
     *)
         echo “Unknown $n”
         exit 1
         ;;
esac

exit 0

}}}

{{item1{選擇目前目錄的 *.sh 檔案}}}

''1. 撰寫程式''
{{{
$ nano selshfile.sh
#!/bin/bash

# This script allows you to select a file ending in the .sh extension (in the current directory)
echo "Please Select the RESTORE FILE you would like to restore: "

select RESTOREFILE in *.sh; do
      break 
done

echo "The Restore File you selected was: ${RESTOREFILE}"
}}}

''2. 執行結果''
{{{
$ ./selshfile.sh
Please Select the RESTORE FILE you would like to restore:
1) couter.sh
2) selshfile.sh
3) testd.sh
4) teste.sh
#? 4
The Restore File you selected was: teste.sh
}}}
<<toBalaNotes "1">>


///%1
//%/
''參考文章''
1. Mount a remote SSH folder in Ubuntu (cmd and GUI)
http://howto.blbosti.com/2010/09/mount-a-remote-ssh-folder-in-ubuntu-cmd-and-gui/

Connecting to a server across the internet is much more secure using SSH. There is a way that you can mount a folder on a remove server using the SSHFS service (based on the SSH File Transfer Protocol).

Open terminal and follow these steps:
{{{
$ sudo apt-get install sshfs
[sudo] password for student:
正在讀取套件清單... 完成
正在重建相依關係
正在讀取狀態資料... 完成
下列【新】套件將會被安裝:
  sshfs
升級 0 個,新安裝 1 個,移除 0 個,有 14 個未被升級。
需要下載 40.8kB 的套件檔。
此操作完成之後,會多佔用 143kB 的磁碟空間。
下載:1 http://tw.archive.ubuntu.com/ubuntu/ lucid/main sshfs 2.2-1build1 [40.8kB]
取得 40.8kB 用了 0s (120kB/s)
選取了原先未被選取的套件 sshfs。
(正在讀取資料庫 ... 系統目前共安裝了 48733 個檔案和目錄。)
正在解開 sshfs (從 .../sshfs_2.2-1build1_i386.deb)...
正在進行 man-db 的觸發程式 ...
正在設定 sshfs (2.2-1build1) ...
}}}

2. Add yourself to the fuse group
{{{
$ sudo adduser student fuse
在 'student' 群組中新增了 'fuse' 使用者 ...
Adding user student to group fuse
完成。
$ cat /etc/group | grep fuse
fuse:x:104:student
}}}

3. Log out and in again
{{{
$ logout
}}}

4. Create a directory to mount the remote folder in (eg. in your home directory or in /media…)
{{{
$ mkdir  ~/backup
}}}

5. Mount the remote server
{{{
$ sshfs username@host:/remotepath ~/backup
}}}
You'll be prompted to save the server key and for your remote password.

Now you should be able to cd into the directory and start using it as if it was local.

6. To unmount sshfs enter this command
{{{
$ fusermount -u ~/backup
}}}
<<toBalaNotes "1">>


///%1
//%/
語系設定在 Ubuntu 9.10 之前的版本, 都是編輯 /etc/locale.gen 此檔案, 再執行 locale-gen 即可. 但在 Ubuntu Linux 9.10 及以後的版本, 語系增加與設定, 操作步驟如下 : 

{{item1{檢視目前支援的語系}}}
{{{
tobala@UB10Serv001:~$ cat /var/lib/locales/supported.d/local
zh_TW BIG5
en_US.UTF-8 UTF-8
}}}

{{item1{Locales 增加}}}
要增加語系可以有下述兩種做法: (註: 語系列表可見: /usr/share/i18n/SUPPORTED)

{{op1{1. 手動加入語系}}}
{{{
$ sudo nano /var/lib/locales/supported.d/zh # 隨意新增一個檔案(zh 這個檔名可隨意命名)

zh_CN.UTF-8 UTF-8
zh_SG.UTF-8 UTF-8
zh_HK.UTF-8 UTF-8
zh_TW.UTF-8 UTF-8 
}}}

{{op1{2. 使用 locale-gen 加入語系}}}
{{{
$ sudo locale-gen zh_TW
Generating locales...
  zh_TW.BIG5... done
Generation complete.

$ sudo locale-gen zh_TW.UTF-8
Generating locales...
  zh_TW.UTF-8... done
Generation complete.

$ cat /var/lib/locales/supported.d/local             # 加入完成後, 可於此檔案看到
en_US.UTF-8 UTF-8
zh_TW BIG5
zh_TW.UTF-8 UTF-8
}}}

{{item1{重新建立 Locales}}}
{{{
$ sudo locale-gen
Generating locales...
  en_AG.UTF-8... done
  en_AU.UTF-8... done
  en_BW.UTF-8... done
  en_CA.UTF-8... done
  en_DK.UTF-8... done
  en_GB.UTF-8... done
  en_HK.UTF-8... done
  en_IE.UTF-8... done
  en_IN.UTF-8... done
  en_NG.UTF-8... done
  en_NZ.UTF-8... done
  en_PH.UTF-8... done
  en_SG.UTF-8... done
  en_US.UTF-8... done
  en_ZA.UTF-8... done
  en_ZW.UTF-8... done
  zh_TW.BIG5... up-to-date
  zh_TW.UTF-8... up-to-date
Generation complete.

$ ls /usr/lib/locale/
en_AG       en_CA.utf8  en_HK.utf8  en_NG       en_SG.utf8  en_ZW.utf8
en_AU.utf8  en_DK.utf8  en_IE.utf8  en_NZ.utf8  en_US.utf8  zh_TW
en_BW.utf8  en_GB.utf8  en_IN       en_PH.utf8  en_ZA.utf8  zh_TW.utf8
}}}

{{item1{指定語系}}}
編輯 /etc/default/locale 檔案, 設定如下 : .
{{{
LANG="zh_TW.UTF-8"
}}}

{{item1{重新開機}}}
{{{
$ sudo reboot
}}}
<<toBalaNotes "locales">>

''問題 : 為何在 Ubuntu Server 安裝的中文語系,在終端機文字介面部分顯示亂碼,該怎麼把文字介面改回英文語系?''

''回答 :''

系統中必須有存在 en_US.UTF-8 及 en_US.ISO-8859-1 語系資料, 執行下式檢視是否安裝 ?
{{{
$ sudo locale-gen
}}}

如沒安裝執行下式 :
{{{
$ sudo locale-gen en_US.UTF-8
$ sudo locale-gen en_US
  en_US.ISO-8859-1.....
}}}

確認有存在 en_US.UTF-8 語系資料, 這時便可修改登入帳號的家目錄中的 ''.bashrc'' 程序檔, 內容如下 :
{{{
                         :
if [ -z "$SSH_TTY" ]; then                 #  如是 ssh 連接還是使用 LANG=zh_TW.UTF-8 這設定
   export LANG=en_US.UTF-8
   export LANGUAGE=en_US
   export LC_ALL=en_US.UTF-8
else
   export LC_ALL=zh_TW.UTF-8
fi
}}}
之後就不會看到亂碼了(英文顯示), 並且可正常按 Tab 鍵


///%locales
//%/
@@font-size:16px;
Linux 系統本身就是一個 “文字資料庫”, 系統管理者可透過豐沛的 “文字處理命令”, 來應用此資料庫, 更可透過 Bash 程式來使管理自動化
@@
{{item1{clear : 清除終端機畫面}}}
{{{
$ clear 
}}}

{{item1{cat : 顯示文字檔內容}}}
{{{
$ cat  .bashrc  -n                      (顯示行號)

$ cat .bashrc -n | grep 33

$ tac  .bashrc      (倒著顯示內容)
}}}

{{item1{設定文字顏色}}}
{{{
$ echo -e '\E[37;32m'             (黑底綠字)
$ echo abc
$ tput sgr0                           (Reset colors to normal)
}}}

''[註]'' Colorizing Scripts 網址 : http://www.tldp.org/LDP/abs/html/colorizing.html

{{item1{顯示本機 IP 位址}}}
{{{
# ifconfig | grep 'inet addr' | tr -s ' '
 inet addr:192.168.200.140  Bcast:192.168.200.255  Mask:255.255.255.0
 inet addr:127.0.0.1  Mask:255.0.0.0
}}}

''[註]'' "tr -s" 將多個空白變成一個空白 

''[練習]'' 以下 ''tr -d ' ''' 這行功能為何 ?
{{{
$ var='hello world'
$ var=$( echo "$var" | tr -d ' ' )
$ echo $var
helloworld
}}}

''[練習]'' 將 ethx 及 IP 位址合為一行
{{{
$ ifconfig -a | grep -A1 eth1 | tr -d '\n'
}}}

{{item1{od (dump files in Octal and other formats)}}}
{{{
$ nano  od.txt
a1 \n
A1 \n
ABC \t ABC

$ od –t  a  od.txt
0000000  a  1  sp  nl  A  1  sp  nl


$ od –t  x1  od.txt
0000000  61  31  20  0a  41  32  20  0a
}}}

{{item1{wc (print the number of bytes, words, and lines in files)}}}
{{{
$ wc  -l  /etc/resolv.conf

$ wc  -c  /etc/resolv.conf

$ wc –w /etc/resolv.conf

$ wc  /etc/resolv.conf
2  4  12   /etc/resolv.conf
}}}

{{item1{cut}}}
{{{
$ cat  /etc/passwd

$ cut  -d:  -f1  /etc/passwd
root
daemon
bin
sys
         :
haldaemon
postgres
ebox

$ cut  -c1   /etc/passwd
          :
g
m
n
u
              :
}}}

{{item1{製作 length 命令}}}
{{{
$ mkdir ~/bin                         (請將所有 Bash Script 存入 ~/bin 目錄中, 因 ~/bin 目錄, 會自動加入 PATH 環境變數)
$ cd ~/bin


$ nano  length
ls -lh  $1  |  fmt -u | cut  -d' '  -f5

[註] fmt 參數
-u, --uniform-spacing     one space between words, two after sentences

$ chmod  +x  length

$ logout                             (登出)

$ length  /etc/passwd
1292
}}}

{{item1{顯示記憶體大小}}}
{{{
$ free -mo
             total       used       free     shared    buffers     cached
Mem:           244         60        184          0          5         31
Swap:          400          0        400

$ free -mo | grep Mem
Mem:           244         60        184          0          5         31

$ free -mo | grep Mem | fmt -u
Mem: 244 60 183 0 5 31

$ free -mo | grep Mem | fmt -u | cut -d' ' -f2
244
}}}
<<toBalaNotes "textcmd">>

{{item1{由 Bash Script 去設定 TCP/IP 網路}}}
''$ nano setip.sh''
{{{
#!/bin/bash
ifconfig eth0 192.168.1.100/24                                       # Configure static ip & subnet mask
route add default gw 192.168.1.1                                     # Set the Default Gateway
echo nameserver 192.168.1.1 > /etc/resolv.conf         # Add DNS Server
}}}


///%textcmd
//%/
''參考文章''
1. How to Backup and Restore your Home directory
http://mylinuxramblings.wordpress.com/2010/01/10/how-to-backup-and-restore-your-home-directory/
2. Linux Tar 的使用方法
http://sblog.missv.tw/2009/08/linux-tar.html
3. Backup and Restore Your Ubuntu System using Sbackup
http://www.debianadmin.com/backup-and-restore-your-ubuntu-system-using-sbackup.html

Linux 上常見的壓縮指令就是 ''gzip'' 與 ''bzip2'' ,至於 ''compress'' 已經退流行了。 ''gzip'' 是由 GNU 計畫所開發出來的壓縮指令,該指令已經取代了 compress 。 後來 GNU 又開發出 ''bzip2'' 這個壓縮比更好的壓縮指令!不過,這些指令通常僅能針對一個檔案來壓縮與解壓縮,如此一來, 每次壓縮與解壓縮都要一大堆檔案,豈不煩人?此時,那個所謂的『打包軟體, tar』就顯的很重要啦!

{{item1{tar 打包軟體}}}

''格式''
tar [-cxtzjvfpPN]  文件與目錄 ....

''參數:''
{{{
-c :建立一個壓縮文件的參數指令(create 的意思);
-x :解開一個壓縮文件的參數指令!
-t :查看 tarfile 裡面的文件!
特別注意,在參數的下達中, c/x/t 僅能存在一個!不可同時存在!因為不可能同時壓縮與解壓縮。

-z :是否同時具有 gzip 的屬性?亦即是否需要用 gzip 壓縮?
-j :是否同時具有 bzip2 的屬性?亦即是否需要用 bzip2 壓縮?
-v :壓縮的過程中顯示文件!這個常用,但不建議用在背景執行過程!
-f :使用檔名,請留意,在 f 之後要立即接檔名喔!不要再加參數!
例如使用『 tar -zcvfP tfile sfile'就是錯誤的寫法,要寫成『 tar -zcvPf tfile sfile'才對喔!

-p :使用原文件的原來屬性(屬性不會依據使用者而變)
-P :可以使用絕對路徑來壓縮!
-N :比後面接的日期(yyyy/mm/dd)還要新的才會被打包進新建的文件中!
--exclude FILE:在壓縮的過程中,不要將 FILE 打包! 
}}}

對於剛剛接觸 Linux 的人來說,一定會給 Linux 下一大堆各式各樣的文件名給搞暈。別個不說,單單就壓縮文件為例,我們知道在Windows 下最常見的壓縮文件就只有兩種,一是 ,zip,另一個是 .rar。可是Linux 就不同了,它有.gz、.tar.gz、tgz、bz2、.Z、.tar 等眾多的壓縮文件名,此外 windows 下的 .zip 和 .rar 也可以在 Linux 下使用,不過在 Linux 使用 .zip 和 .rar 的人就太少了。本文就來對這些常見的壓縮文件進行一番小結,希望你下次遇到這些文件時不至於被搞暈:)

在具體總結各類壓縮文件之前呢,首先要弄清兩個概念:打包和壓縮。打包是指將一大堆文件或目錄什麼的變成一個總的文件,壓縮則是將一個大的文件通過一些壓縮算法變成一個小文件。為什麼要區分這兩個概念呢?其實這源於 Linux 中的很多壓縮程序只能針對一個文件進行壓縮,這樣當你想要壓縮一大堆文件時,你就得先借助另它的工具將這一大堆文件先打成一個包,然後再就原來的壓縮程序進行壓縮。

Linux 下最常用的打包程序就是 tar了,使用 tar 程序打出來的包我們常稱為 tar 包,tar 包文件的命令通常都是以 .tar 結尾的。生成 tar 包後,就可以用其它的程序來進行壓縮了,所以首先就來講講 tar 命令的基本用法:

tar 命令的選項有很多(用man tar可以查看到),但常用的就那麼幾個選項,下面來舉例說明一下:
{{{
# tar -cf all.tar *.jpg
}}}
這條命令是將所有.jpg 的文件打成一個名為 all.tar 的檔案。 -c 是表示產生新的包,-f 指定包的文件名。

{{{
# tar -rf all.tar *.gif
}}}
這條命令是將所有 .gif 的文件增加到 all.tar 的包裡面去。-r 是表示增加文件的意思。

{{{
# tar -uf all.tar logo.gif
}}}
這條命令是更新原來 all.tar 中 logo.gif 文件,-u 是表示更新文件的意思。

{{{
# tar -tf all.tar
}}}
這條命令是列出 all.tar 中所有文件,-t 是列出文件的意思

{{{
# tar -xf all.tar
}}}
這條命令是解出 all.tar 中所有文件,-x 是解開的意思

以上就是 tar 的最基本的用法。

{{item1{實作}}} 

''1. 將 $HOME/bin 內容, 壓縮至 bin.tar.gz''
{{{
$ tar czf bin.tar.gz bin/
}}}

''2. 檢視壓縮檔內容''
{{{
$ tar -tf bin.tar.gz
bin/
bin/netchk.sh
bin/Expect_Example/
bin/Expect_Example/test_var_deref.txt
bin/Expect_Example/test_self_include.txt
bin/Expect_Example/test_cond_loop.txt
bin/Expect_Example/self_test_all.elt
          :
bin/Expect_Example/self_test_fork.txt
bin/Expect_Example/debug.inc
bin/Expect_Example/test_expect_random.txt
bin/setup_local_ssh.sh
bin/sshrun.sh
bin/data/
bin/data/ttyS0.conf
bin/data/bashrc.txt
bin/data/netid.txt
bin/sysprep.sh
bin/expect-lite
}}}

<<toBalaNotes "tar">>

''參考文章''
1. Ubuntu Linux backup of a laptop using a USB enclosure and the dump utility
http://baheyeldin.com/technology/linux/ubuntu-linux-backup-of-a-laptop-using-a-usb-enclosure-and-the-dump-utility.html
2. Ubuntu BackupYourSystem
https://help.ubuntu.com/community/BackupYourSystem

{{item1{快速備份 Ubuntu 系統的方法}}}
使用命令模式, 就算沒有安裝桌面,也可以直接透過 SSH 來完成系統備份, 方法很簡單,你只需執行一行命令, 就可以搞定, 如下 :

''進行備份:''
{{{
tar -cvpzf /backup/kvmbackup.tgz -exclude=/proc -exclude=/lost+found -exclude=/mnt –exclude=/sys –exclude=/media /
}}}
tar 命令參數說明 :
{{{
c – 新建一個備份檔
v – 詳細模式, tar 程式將在螢幕上即時輸出所有資訊。
p – 保存權限,並應用到所有檔。
z – 採用 ‘gzip’ 壓縮備份檔案,以減小備份檔案體積。
f – 指定備份檔案名稱。
}}}

''進行還原:''
{{{
tar -xvpzf /backup/kvmbackup.tgz -C /
}}}
在你沒有對 Linux 系統架構很熟前,千萬不要輕易的把一台 Server 的備分 "直接" 覆蓋到另一台上。

''如需圖形備份軟體, 可參考以下網址 :''
http://www.debianadmin.com/backup-and-restore-your-ubuntu-system-using-sbackup.html

<<toBalaNotes "2">>

{{item1{rar}}}
rar 是 Windows 系統中很廣範的壓縮檔,因此 ubuntu 中會時常需要用到它。
以下簡 介ubuntu10.04 中,在終端機模式下, rar 的安裝、壓縮及解壓縮的步驟

''Step 1. 安裝方式''
{{{
$ sudo apt-get install rar
}}}
假設我們當前目錄下,有個子目錄叫 files
{{{
$ tree files

files
|– aa.txt
`– bb.txt
}}}
而在files目錄下有兩個檔案 aa.txt and bb.txt, 而我們希望把整個 files目錄作壓縮,然後再解壓縮。

那麼操作方式如下:

''Step 2. 壓縮 compressing''
{{{
$ rar a ./files.rar ./files
}}}
因此當前目錄下,多出了一個 files.rar

''Step 3. 解壓縮 decompressing''
{{{
$ rar x ./files.rar
}}}
<<toBalaNotes "3">>

///%tar
//%/

///%2
//%/

///%3
//%/
{{item1{Trapping ctrl-c in Bash}}}
You can use the trap builtin to handle a user pressing ctrl-c during the execution of a Bash script. e.g. if you need to perform some cleanup functions.

{{{
#!/bin/bash

# trap ctrl-c and call ctrl_c()
trap ctrl_c INT

function ctrl_c() {
        echo "** Trapped CTRL-C"
}

for i in `seq 1 5`; do
    sleep 1
    echo -n "."
done
}}}

<<toBalaNotes "1">>

{{item1{Shell Script Disable CTRL C / CTRL Z}}}

''$ nano nostopall.sh''
{{{
#!/bin/bash
# at start add
trap "" 2 20

# your script 
echo " Test"

# loop for sleep
sleep 5
}}}

''trap -l'' command list all signals
{{{
20 is for CTRL + Z
2 is for CTRL  + C
}}}

Here is full list created by ''trap -l'' command:
{{{
 1) SIGHUP     2) SIGINT     3) SIGQUIT     4) SIGILL
 5) SIGTRAP     6) SIGABRT     7) SIGBUS     8) SIGFPE
 9) SIGKILL    10) SIGUSR1    11) SIGSEGV    12) SIGUSR2
13) SIGPIPE    14) SIGALRM    15) SIGTERM    16) SIGSTKFLT
17) SIGCHLD    18) SIGCONT    19) SIGSTOP    20) SIGTSTP
21) SIGTTIN    22) SIGTTOU    23) SIGURG    24) SIGXCPU
25) SIGXFSZ    26) SIGVTALRM    27) SIGPROF    28) SIGWINCH
29) SIGIO    30) SIGPWR    31) SIGSYS    34) SIGRTMIN
35) SIGRTMIN+1    36) SIGRTMIN+2    37) SIGRTMIN+3    38) SIGRTMIN+4
39) SIGRTMIN+5    40) SIGRTMIN+6    41) SIGRTMIN+7    42) SIGRTMIN+8
43) SIGRTMIN+9    44) SIGRTMIN+10    45) SIGRTMIN+11    46) SIGRTMIN+12
47) SIGRTMIN+13    48) SIGRTMIN+14    49) SIGRTMIN+15    50) SIGRTMAX-14
51) SIGRTMAX-13    52) SIGRTMAX-12    53) SIGRTMAX-11    54) SIGRTMAX-10
55) SIGRTMAX-9    56) SIGRTMAX-8    57) SIGRTMAX-7    58) SIGRTMAX-6
59) SIGRTMAX-5    60) SIGRTMAX-4    61) SIGRTMAX-3    62) SIGRTMAX-2
63) SIGRTMAX-1    64) SIGRTMAX
}}}

<<toBalaNotes "2">>




///%1
//%/

///%2
//%/
''參考文章''
1. Pro Git
http://progit.org/book/
2. Git Reference
http://gitref.org/
3. Generating SSH keys (Win/msysgit)
http://help.github.com/msysgit-key-setup/

{{item1{申請  github 帳號}}}

網址 : http://github.com

{{item1{建置開發主機}}}

{{op1{1. 安裝 git 套件}}}
''$ sudo apt-get install git-core''
{{{
[sudo] password for tobala: 
正在讀取套件清單... 完成
正在重建相依關係          
正在讀取狀態資料... 完成
下列的額外套件將被安裝:
  libdigest-sha1-perl liberror-perl
建議套件:
  git-doc git-arch git-cvs git-svn git-email git-daemon-run git-gui gitk
  gitweb
下列【新】套件將會被安裝:
  git-core libdigest-sha1-perl liberror-perl
升級 0 個,新安裝 3 個,移除 0 個,有 336 個未被升級。
需要下載 5,673kB 的套件檔。
此操作完成之後,會多佔用 11.9MB 的磁碟空間。
是否繼續進行 [Y/n]?
}}}

{{op1{2. 建立 root 帳號的 Public Key}}}

''$ ssh-keygen -t rsa -C "oc99.98@gmail.com"''
{{{
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
e8:ae:60:8f:38:c2:98:1d:6d:84:60:8c:9e:dd:47:81 oc99.98@gmail.com
}}}

''[註]'' 這樣會產生 id_rsa 和 id_rsa.pub 二個檔案, 前者是 private key 後者是 public key.

{{op1{3. 請將 /root/.ssh/id_rsa 這檔案內容, 上傳至 GitHub 網站}}}

請到 GitHub 網站, 執行 SSH Public Key 建立

<html>
<img src="img/github01.png" width="80%" height="80%"/>
</html>

<html>
<img src="img/github02.png" width="80%" height="80%"/>
</html>

{{op1{3. 連線測通}}}

''$ ssh git@github.com''
{{{
# ssh git@github.com
The authenticity of host 'github.com (207.97.227.239)' can't be established.
RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,207.97.227.239' (RSA) to the list of known hosts.
PTY allocation request failed on channel 0
Hi CloudWalker/oc99.98! You've successfully authenticated, but GitHub does not provide shell access.
    Connection to github.com closed.
}}}

<<toBalaNotes "1">>

///%1
//%/
{{item1{/etc/shadow 密碼格式}}}
''1. 安裝 mkpasswd 套件''
{{{
$ apt-get install mkpasswd
}}}

''2. 產生密碼''
{{{
$ mkpasswd -m SHA-512 student
$6$8B4ZLIZhHzHeCG$81vGiTewo8QFHsDUUQcJDubEs8tvAmOFTB6/pD1tA7iUnVG0rPIB7o9EziEwjaI6UMxVY6mgsYjol4Nlvpfyf1
}}}

''[註]'' $6 代表 SHA-512

''3. 使用 SLAT 產生密碼''
{{{
$ mkpasswd -S 4UAtDH1X -m SHA-512 student
$6$4UAtDH1X$62Xo.GFyrOPek5DiaskYE31Yf1BC4B764ZFjkVWt6XRLKaRG4TSEnX7Wh6gXzrB5FV.WvierPqWGj0HUAa1Jc1
}}}

''[註]'' 第二個 $ 與 第三個 $ 之間就是 SLAT

''4. 驗證使用者密碼''
{{{
$ p=$(mkpasswd -S 4UAtDH1X -m SHA-512 student)

$ grep $p /etc/shadow

$ echo $?                       # 顯示 0 代表 驗證成功

}}}

<<toBalaNotes "1">>

///%1
//%/
{{item1{Declare simple bash array}}}

''1. 程式撰寫''
{{{
$ nano array01.sh

#!/bin/bash
#Declare array with 4 elements
ARRAY=( 'Debian Linux' 'Redhat Linux' Ubuntu Linux )
# get number of elements in the array
ELEMENTS=${#ARRAY[@]}

# echo each element in array 
# for loop
for (( i=0;i<$ELEMENTS;i++)); do
    echo ${ARRAY[${i}]}
done 
}}}

''2. 執行結果''
{{{
# ./array01.sh 
Debian Linux
Redhat Linux
Ubuntu
Linux
}}}

Declare simple bash array


''$ nano array1.sh''
{{{
i=0
s=65    # decimal ASCII "A"
for f in *.sh
do
    files[i]="$s"
    files[i+1]="$f"    # save file name
    ((i+=2))
    ((s++))
done
echo "${files[@]}"
}}}

''執行結果''
{{{
$ ./array1.sh
65 array1.sh 66 couter.sh 67 select.sh 68 testd.sh 69 teste.sh
}}}
本文網址 : http://en.wikipedia.org/wiki/Loop_device

In Unix-like  operating systems, a loop device, vnd (vnode disk), or lofi  (loopback file interface) is a pseudo-device that makes a file  accessible as a block device.

Before use, a loop device must be connected to an existing file in the filesystem. The association provides the user with an API that allows the file to be used in place of a block special file (cf. device file system). Thus, if the file contains an entire file system, the file may then be mounted as if it were a disk device.

Files of this kind are often used for CD ISO images and floppy disc images. Mounting a file containing a filesystem via such a loop mount makes the files within that filesystem accessible. They appear in the mount point directory.

A loop device may allow some kind of data elaboration during this redirection. For example, the device may be the unencrypted version of an encrypted file. In such a case, the file associated with a loop device may be another pseudo-device. This is mostly useful when this device contains an encrypted file system. If supported, the loop device is in this case the decrypted version of the original encrypted file and can therefore be mounted as if it were a normal filesystem.

<<toBalaNotes "loopdev">>
{{item1{Loop device 實作}}}
本文網址 : http://www.ibm.com/developerworks/linux/library/l-linux-filesystem/
Associating a file system to a storage device in Linux is a process called mounting. The mount command is used to attach a file system to the current file system hierarchy (root). During a mount, you provide a file system type, a file system, and a mount point.

To illustrate the capabilities of the Linux file system layer (and the use of mount), create a file system in a file within the current file system. This is accomplished first by creating a file of a given size using dd (copy a file using /dev/zero as the source) -- in other words, a file initialized with zeros, as shown in Listing 1.

''Listing 1. Creating an initialized file''
{{{
$ dd if=/dev/zero of=file.img bs=1k count=10000
10000+0 records in
10000+0 records out
10240000 bytes (10 MB) copied, 0.0074995 s, 137 MB/s
}}}
You now have a file called file.img that's 10MB. 

''[註]'' /dev/zero 是一個特殊的設備,從這個設備中,讀取的內容,全部都是 0 。

Use the losetup command to associate a loop device with the file (making it look like a block device instead of just a regular file within the file system):
{{{
# 檢視系統預載 loop 裝置
$ ll /dev/loop[0-9]*
brw-rw---- 1 root disk  7,   0  7月 11 12:39 /dev/loop0
brw-rw---- 1 root disk  7,   1  7月 11 12:39 /dev/loop1
brw-rw---- 1 root disk  7,   2  7月 11 12:39 /dev/loop2
brw-rw---- 1 root disk  7,   3  7月 11 12:39 /dev/loop3
brw-rw---- 1 root disk  7,   4  7月 11 12:39 /dev/loop4
brw-rw---- 1 root disk  7,   5  7月 11 12:39 /dev/loop5
brw-rw---- 1 root disk  7,   6  7月 11 12:39 /dev/loop6
brw-rw---- 1 root disk  7,   7  7月 11 12:39 /dev/loop7

# 將 disk.img 掛載在 /dev/loop0 裝置
$ sudo losetup /dev/loop0 file.img

# 檢視 /dev/loop0 掛載資訊
$ sudo losetup /dev/loop0 
/dev/loop0: [0811]:8917357 (/home/student/KVM/iKVM/file.img)
}}}

With the file now appearing as a block device (represented by /dev/loop0), create a file system on the device with mke2fs. This command creates a new second ext2 file system of the defined size, as shown in Listing 2.

''Listing 2. Creating an ext2 file system with the loop device''
{{{
$ sudo mkfs.ext4 /dev/loop0
mke2fs 1.42 (29-Nov-2011)
Discarding device blocks: done                            
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
2512 inodes, 10000 blocks
500 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=10485760
2 block groups
8192 blocks per group, 8192 fragments per group
1256 inodes per group
Superblock backups stored on blocks: 
	8193

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (1024 blocks): done
Writing superblocks and filesystem accounting information: done
}}}

The file.img file, represented by the loop device (/dev/loop0), is now mounted to the mount point /mnt/point1 using the mount command. Note the specification of the file system as ext2. When mounted, you can treat this mount point as a new file system by doing using an ls command, as shown in Listing 3.

''Listing 3. Creating a mount point and mounting the file system through the loop device''
{{{
$ mkdir /tmp/loop0

$ sudo mount -t ext4 /dev/loop0 /tmp/loop0

$ ls -al /tmp/loop0/
總計 17
drwxr-xr-x  3 root root  1024  7月 11 13:40 .
drwxrwxrwt 12 root root  4096  7月 11 13:23 ..
drwx------  2 root root 12288  7月 11 13:20 lost+found
}}}

As shown in Listing 4, you can continue this process by creating a new file within the new mounted file system, associating it with a loop device, and creating another file system on it.

''Listing 4. Creating a new loop file system within a loop file system''
{{{
$ dd if=/dev/zero of=/mnt/point1/file.img bs=1k count=1000
1000+0 records in
1000+0 records out
$ losetup /dev/loop1 /mnt/point1/file.img
$ mke2fs -c /dev/loop1 1000
mke2fs 1.35 (28-Feb-2004)
max_blocks 1024000, rsv_groups = 125, rsv_gdb = 3
Filesystem label=
...
$ mkdir /mnt/point2
$ mount -t ext2 /dev/loop1 /mnt/point2
$ ls /mnt/point2
lost+found
$ ls /mnt/point1
file.img lost+found

}}}

''Listing 5. Umountting a mount point and umounting the file system through the loop device''
{{{
$ sudo umount /tmp/loop0/

$ sudo losetup -d /dev/loop0
}}}

From this simple demonstration, it's easy to see how powerful the Linux file system (and the loop device) can be. You can use this same approach to create encrypted file systems with the loop device on a file. This is useful to protect your data by transiently mounting your file using the loop device when needed.

{{item1{Loop 裝置另一種實作方式}}}
{{{

# 以下命令會自動將 file.img 掛載到 /dev/loop0, 然後再將 /dev/loop0 掛載到 /tmp/loop0
$ sudo mount -o loop file.img /tmp/loop0

$ ll /tmp/loop0/
總計 17
drwxr-xr-x  3 root root  1024  7月 11 13:22 ./
drwxrwxrwt 12 root root  4096  7月 11 13:23 ../
-rw-r--r--  1 root root     0  7月 11 13:22 hello
drwx------  2 root root 12288  7月 11 13:20 lost+found/

# 以下命令證明 file.img 有掛載到 /dev/loop0
$ sudo losetup /dev/loop0
/dev/loop0: [0811]:8917357 (/home/student/KVM/iKVM/file.img)

# 以下命令會自動將 file.img 從 /dev/loop0 卸掛載
$ sudo umount /tmp/loop0

$ sudo losetup /dev/loop0
loop:無法取得裝置上的資訊 /dev/loop0: 沒有此一裝置或位址
}}}

<<toBalaNotes "vfsdo">>

{{item1{建立與使用 RamDisk}}}
建立 ramdisk 空間的方式,是用 dd 指令,填入指定大小的內容後, 就會在 ram 中保留該大小的空間;而這個 ram 空間,就連接到 dd 指 令中,所指定的設備名稱,如 /dev/ram0 。
{{{
$ dd if=/dev/zero of=/dev/ram0 bs=1k count=4096
}}}
上面這指令的意義是,從輸入設備 /dev/zero 中,以 bs 指定的大小(1k), 讀取資料,輸出到設備 /dev/ram0 中,重覆輸出入 count 指定的次 數(4096次)。這表示 /dev/ram0 所連接的 ram 空間,會有 4096K 的空間可用。

/dev/zero 是一個特殊的設備,從這個設備中,讀取的內容,全部都是 0 。

ramdisk 可以建立的很大,但我們只是要找一個空間,供我們製作 root disk ,因為一塊軟碟片的空間不會很大,所以我們也不需要 挖一塊很大的 ram 空間,大概 4096k 就夠了。

雖然一塊 MF-2HD 的磁片,只有 1440K ,但因為我們是要將 root filesystem 的內容,變成 image 檔,再壓縮過一次後,才放入磁片裡, 所以這塊要做為 root filesystem 的空間,可以大於 1440K 。

格式化這塊 ram 空間,因為 minix 檔案系統格式比較省空間,所以 用這格式:
{{{
$ mkfs.minix /dev/ram0 4096
}}}
最後 mount 此空間 (我 mount 在 /mnt/rootfs 目錄上),準備複製檔案:
{{{
$ mount -t minix /dev/ram0 /mnt/rootfs 
}}}


///%loopdev
//%/

///%vfsdo
//%/
Midnight Commander 官網 : http://www.midnight-commander.org/

This is definitely one of the consecrated file managers on Linux. ''Midnight Commander'' is a ''terminal-based'' (it uses a text user interface), twin-panel file manager with powerful features and ease of use, and it still is one of the popular file managers out there, especially that it can be successfully used on a system which does not have the X Window System installed.

{{item1{安裝 Midnight Commander}}}
{{{
$ sudo apt-get install mc
}}}
{{item1{使用 Midnight Commander}}}

''1. 啟動 mc''
{{{
$ sudo mc
}}}

''2. 使用介面''

[img[img/linux/mc/mc01.png]]

<<toBalaNotes "mc">>


///%mc
//%/
''參考文章''
1. LSB 2.0 啟動 Linux 世界新標準時代報導之一
http://forum.icst.org.tw/phpbb/viewtopic.php?f=16&t=7878

{{item1{檢視 Ubuntu 版本代號}}}
{{{
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu lucid (development branch)
Release:        10.04
Codename:       lucid
}}}

{{op1{Ubuntu 版本總表}}}
|''Version''|''Code name''|''Release date''|
|4.10|Warty Warthog|2004-10-20|
|5.04|Hoary Hedgehog|2005-04-08|
|5.10|Breezy Badger|2005-10-13|
|6.06 LTS|Dapper Drake|2006-06-01|
|6.10|Edgy Eft (小蜥蜴)|2006-10-26|
|7.04|Feisty Fawn (小鹿)|2007-04-19|
|7.10|Gutsy Gibbon (長臂猿)|2007-10-18|
|8.04 LTS|Hardy Heron (蒼鷺)|2008-04-24|
|8.10|Intrepid Ibex (野生山羊)|2008-10-30|
|9.04|Jaunty Jackalope (鹿角兔)|2009-04-23|
|9.10|Karmic Koala (無尾熊)|2009-10-29|
|10.04 LTS|Lucid Lynx (山貓)|2010-04-29|

{{item1{Ubuntu OS 是否為 64 位元 ?}}}
Linux users should type the uname command. Depending on the platform, you may see

{{op1{ 64 位元顯示資訊}}}
''$ uname -a''
Linux US1041KVM 2.6.32-24-server #42-Ubuntu SMP Fri Aug 20 15:38:55 UTC 2010 @@color:red;x86_64@@ GNU/Linux

''$ uname -m''
@@color:red;x86_64@@ 

{{op1{32 位元顯示資訊}}}
''$ uname -a''
Linux US1041NAT 2.6.10-1.771_FC2smp #1 SMP Mon Mar 28 01:10:51 EST 2005 i686 i686 @@color:red;i386@@ GNU/Linux

<<toBalaNotes "version">>
{{item1{Linux 標準規範 (LSB)}}}
Linux 標準規範(英語: Linux Standard Base,LSB)是一個在 Linux 基金會(由自由標準組織(FSG)及開放源碼開發實驗室(OSDL)合併)結構下對Linux發行版的聯合項目,使 Linux 作業系統符合軟體系統架構,或檔案系統架構標準的規範及標準。LSB 基於 POSIX,統一 UNIX 規範及其他開放標準,共在某些領域擴展它們。
{{{
The goal of the LSB is to develop and promote a set of open standards that will increase compatibility among Linux distributions and enable software applications to run on any compliant system even in binary form. In addition, the LSB will help coordinate efforts to recruit software vendors to port and write products for Linux Operating System.
}}}
The LSB compliance may be certified for a product by a certification procedure.

LSB 規範的例子: 標準函式庫,一系列的命令和工具以擴大 POSIX 的標準,檔案系統架構的 layout, 執行級別,列印系統, Spooling 如 CUPS 及幾個 X Window 系统的擴展。

///%version
//%/
''參考文章''
1. How to create a local package repository. 
https://help.ubuntu.com/community/AptGet/Offline/Repository

本文網址 : https://help.ubuntu.com/community/AptGet/Offline

You can use the ''Ubuntu Live DVD'' to install packages (i.e. to an older offline Ubuntu computer).

{{item1{1. 放入最新安裝光碟}}}

[img[img/ubuntu10.4/Server/aptcdrom01.png]]

{{op1{2. 執行 apt-cdrom 命令}}}
''apt-cdrom'' can add a new CDROM to APTs sources.list file (list of available repositories). It is necessary to use apt-cdrom to add CDs to the APT system, it cannot be done by hand.

Put the Live CD in the unit and use one of these commands, in this order :

''檢測套件安裝光碟''
{{{
$ sudo apt-cdrom --no-act add
使用光碟機掛載點 /media/apt/
正在識別..[713f2ec9ef73f53777f6a8293710b788-2]
正在掃描碟片中的索引檔..
找到了 2 個套件索引,0 個原始碼索引,0 個翻譯索引及 1 個簽章
找到標籤 'Ubuntu-Server 10.04.1 LTS _Lucid Lynx_ - Release i386 (20100719.1)'
這個碟片名為:
'Ubuntu-Server 10.04.1 LTS _Lucid Lynx_ - Release i386 (20100719.1)'
正在複製套件清單...gpgv: 由 2010年07月19日 (週一) 16時33分05秒 CST 建立的簽章, 使用 DSA 金鑰 ID FBB75451
gpgv: 完好的簽章來自於 "Ubuntu CD Image Automatic Signing Key <cdimage@ubuntu.com>"
Reading Package Indexes... 完成
該碟片的來源列表項目為:
deb cdrom:[Ubuntu-Server 10.04.1 LTS _Lucid Lynx_ - Release i386 (20100719.1)]/ lucid main restricted
請對您的光碟組中的其它光碟重複相同的操作。
W: Skipping nonexistent file /media/apt/dists/lucid/main/binary-i386/Packages
W: Skipping nonexistent file /media/apt/dists/lucid/main/debian-installer/binary-i386/Packages
W: Skipping nonexistent file /media/apt/dists/lucid/restricted/binary-i386/Packages
W: Skipping nonexistent file /media/apt/dists/lucid/restricted/debian-installer/binary-i386/Packages
}}}

''開始建立套件資料庫''
{{{
$ sudo apt-cdrom add        # 實際更新 /etc/apt/source.list

$ cat /etc/apt/sources.list | grep cdrom
# deb cdrom:[Ubuntu-Server 10.04 LTS _Lucid Lynx_ - Release i386 (20100427)]/ lucid main restricted
#deb cdrom:[Ubuntu-Server 10.04 LTS _Lucid Lynx_ - Release i386 (20100427)]/ lucid main restricted
deb cdrom:[Ubuntu-Server 10.04.1 LTS _Lucid Lynx_ - Release i386 (20100719.1)]/ lucid main restricted

$ sudo nano /etc/apt/source.list        # 將所有更新網址註解, 只保留 新增項目 (deb cdrom:[.........]/ lucid main restricted)

$ sudo apt-get update
略過 cdrom://Ubuntu-Server 10.04.1 LTS _Lucid Lynx_ - Release i386 (20100719.1)/ lucid/main Translation-zh_TW
略過 cdrom://Ubuntu-Server 10.04.1 LTS _Lucid Lynx_ - Release i386 (20100719.1)/ lucid/restricted Translation-zh_TW
正在讀取套件清單... 完成

$ sudo apt-get upgrade
正在讀取套件清單... 完成
正在重建相依關係
正在讀取狀態資料... 完成
下列套件將會維持其原有版本:
  linux-generic-pae linux-headers-generic-pae linux-image-generic-pae
  linux-image-virtual linux-virtual
下列套件將會被升級:
  apt apt-transport-https apt-utils base-files grub-common grub-pc
  landscape-common linux-libc-dev update-manager-core ureadahead
升級 10 個,新安裝 0 個,移除 0 個,有 5 個未被升級。
需要下載 0B/5,539kB 的套件檔。
此操作完成之後,會多佔用 152kB 的磁碟空間。
是否繼續進行 [Y/n]?
}}}

''安裝套件''
{{{
$ sudo apt-get install nano

$ sudo apt-get install sqlite
}}}

''Description and options''

add    
{{{
is used to add a new disc to the source list. It will unmount the CDROM device, prompt for a disk to be inserted and then procceed to scan it and copy the index files. If the disc does not have a proper .disk/ directory you will be prompted for a descriptive title. APT uses a CDROM ID to track which disc is currently in the drive and maintains a database of these IDs in /var/lib/apt/cdroms.list
}}}

ident
{{{
is a debugging tool to report the identity of the current disc as well as the stored file name.
}}}

-d : 
{{{
MountPoint (specify the location to mount the cdrom). This mount point must be listed in /etc/fstab and properly configured.
}}}

-r : 
{{{
rename a disc; change the label of a disk or override the disks given label. This option will cause apt-cdrom to prompt for a new label.
}}}

-n: 
{{{
no Changes; Do not change the sources.list file and do not write index files. Everything is still checked however. 
}}}

{{op1{Test}}}
After dist-upgrade you can test that everything is OK
{{{
sudo apt-get -f install
sudo dpkg --configure -a
}}}

<<toBalaNotes "cdromapt">>

///%cdromapt
//%/
''參考文章''
1. Example uses of the Linux Command zip
http://linux.about.com/od/commands/a/blcmdl1_zipx.htm
2. 關於來自windows中文zip壓縮檔的問題
http://kawsing.blogspot.com/2009/06/windowszip.html

{{item1{檢視目前登入環境的語系}}}
{{{
# echo $LANG
zh_TW.UTF-8
}}}

{{item1{撰寫程式}}}

此程式必須在 zh_TW.UTF-8 語系中執行, 並且在系統要先安裝 convmv 命令套件. zipwww.sh 會將家目錄中的 www 目錄壓縮, 壓縮後的檔案, 會複製回 www 目錄

''$ nano zipwww.sh''
{{{
#!/bin/bash

[ "$USER" != "root" ] && echo "要 root 權限" && exit 1
[ "$LANG" != "zh_TW.UTF-8" ] && echo "語系不對, 必須是 zh_TW.UTF-8" && exit 1
which convmv &>/dev/null
[ "$?" != "0" ] && echo "請安裝 convmv (apt-get install convmv)" && exit 1

u=$(ls /home)
echo "" >/tmp/convmv.msg

for z in $u
do
   [ -d /tmp/www ] && rm -r /tmp/www &>/dev/null

   if [ -d /home/$z/www ]; then
      cp -rP /home/$z/www /tmp/www &>/dev/null

      convmv -r --notest -f utf-8 -t big5 /tmp/www &>>/tmp/convmv.msg
      [ "$?" != "0" ] && echo "轉碼失敗" && exit 1

      cd /tmp/ &>/dev/null
      zip -r $z www &>/dev/null
      [ "$?" != "0" ] && echo "$z.zip 壓縮失敗" && exit 1

      cp $z.zip /home/$z/
      chown $z:$z /home/$z/$z.zip
      [ "$?" == "0" ] && echo "$z.zip 產生成功"
    fi

done
}}}

<<toBalaNotes "1">>



///%1
//%/
''參考文章''
1. 例行性工作排程 (crontab)
http://linux.vbird.org/linux_basic/0430cron.php

本文網址 : http://superuser.com/questions/169688/crontab-not-working-in-ubuntu-10-04

There are three different ways to use cron.
{{{
1. Putting scripts in the /etc/cron.hourly , /etc/cron.daily , /etc/cron.weekly or /etc/cron.monthly folders
The system will then run those at the scheduled time with root privileges

2. Editing /etc/crontab
This takes a syntax like the one you were trying to use in crontab -e, because here you can specify which user should be responsible for the scheduled job, in your case, john.

3. The crontab command, which saves a cron tab for the user that made the job in /var/spool/cron/crontabs
}}}
If you are using the third method, you don't need to tell it you are john, it already knows. You can however tell it with the ''-u'' flag to save the job in someone elses cron tab.

Using the third method, you do not need to have the john in ''* * * * * john /home/john/Desktop/test.sh''

<<toBalaNotes "1">>

{{item1{crontab 實作}}}
{{{
$ export EDITOR=nano   # 設定 EDITOR 系統變數,在此請輸入個人慣用的文字編輯器
$ crontab -e          # 撰寫個人 cron jobs table
                      # 此時 crontab 會利用 $EDITOR 這個系統變數,啟動文字編輯器
		      # 用來撰寫個人 crontab 設定檔,請輸入以下內容並存檔後離開。
*/1 * * * * date >> /tmp/date
                      # 此語法表示每一分鐘執行 date 一次。

$ crontab -l             # 列出目前個人的 crontab 設定檔
# m h  dom mon dow   command
*/1 * * * * date >> /tmp/date

# 請等待一分鐘
$ cat /tmp/date
# 請等待一分鐘
$ cat /tmp/date
# 請等待一分鐘
$ rm /tmp/date 
# 請等待一分鐘
$ cat /tmp/date

# 刪除目前個人的排程
$ crontab -r
$ crontab -l
no crontab for student
}}}

{{item1{crontab 格式說明}}}
{{{
*  *  *  *  *     date >> /tmp/date
分 時 日 月 周      執行的命令

# 每個月的 15 號上午 10 點 30 分執行,語法為
30 10 15 * *    [執行的命令]

# 星期日早上 3 點 5 分執行,語法為
5 3 * * 7       [執行的命令]

# 每五分鐘執行一次,語法為
*/5 * * * *     [執行的命令]

以下擷取於 man 5 crontab 用來說明各欄位允許的值
              field          allowed values
              -----          --------------
              minute         0-59
              hour           0-23
              day of month   1-31
              month          1-12 (or names, see below)
              day of week    0-7 (0 or 7 is Sun, or use names)
}}}

{{item1{系統定期的 cron jobs}}}
{{{
$ cat /etc/crontab 

# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file.
# This file also has a username field, that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user  command
25 6    * * *   root    test -e /usr/sbin/anacron || run-parts --report /etc/cron.daily
47 6    * * 7   root    test -e /usr/sbin/anacron || run-parts --report /etc/cron.weekly
52 6    1 * *   root    test -e /usr/sbin/anacron || run-parts --report /etc/cron.monthly
#
}}}

{{item1{/etc/crontab 說明}}}
{{{
# 25 6    * * * 每天早上六點 25 分,執行存放在 /etc/cron.daily 下安排的所有工作
# 47 6    * * 7 禮拜天早上六點 47 分,執行存放在 /etc/cron.weekly 下安排的所有工作
# 52 6    1 * * 每個月一號早上六點 52 分,執行存放在 /etc/cron.monthly 下安排的所有工作
}}}

您只要將您所撰寫好的 shell script 存放在 /etc/cron.daily 就可以達到每天定期執行的效果。在此提供一備份的 shell script 提供給讀者參考。 你可以將他放置在 /etc/cron.weekly 這樣就可每周定期執行備份工作。
{{{
$ nano /etc/cron.weekly/backup-utils

#!/bin/bash
SOURCE_DIR="/etc /var /home"    # 填入你想備份的目錄
BACKUP_DIR="/backup"            # 填入你想備份到那個目錄下,筆者預設為 /backup
BACKUP_NAM="BACKUP-"            # 填入你想備份後的檔名開頭名稱為

DATE=$(date +%m%d)          
FILE_NAME="${BACKUP_DIR}/${BACKUP_NAM}${DATE}.tgz"

tar cvfz $FILE_NAME $SOURCE_DIR

$ chmod +x /etc/cron.weekly/backup-utils
}}}

///%1
//%/

{{{
*
?
[character]
[!character]
[a-z]
{frag1,frag2,frag3}
}}}

''範例 1''
{{{
$ ls  a*

$ ls  a?b*

$ ls [ab]*
}}}

''範例 2''
{{{
$ echo string_{a,b,c}
}}}

''範例 3''
{{{
$ cp  file1 file2 file[567]  ~
}}}

''範例 4''
{{{
$ head .bash{rc,_history}
==> .bashrc <==
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

# don't put duplicate lines in the history. See bash(1) for more options
# don't overwrite GNU Midnight Commander's setting of `ignorespace'.
export HISTCONTROL=$HISTCONTROL${HISTCONTROL+,}ignoredups

==> .bash_history <==
sudo shutdown -h now
ifconfig -a
setterm -blength 0 -powersave off -blank 0 inversescreen
setterm -blength 0 -powersave off -blank 0 -inversescreen
setterm -blength 0 -powersave off -blank 0 -inversescreen off
sudo shutdown -h now
clear
apt-get update
clear
apt-get update
}}}

{{op1{顯示檔名中第四個字為 n 的檔案}}}
{{{
$ ls -al /bin/???n*
-rwsr-xr-x 1 root root 76228 2009-02-19 03:43 /bin/mount
-rwxr-xr-x 1 root root  5400 2009-03-31 17:02 /bin/mountpoint
lrwxrwxrwx 1 root root     6 2009-06-15 10:12 /bin/open -> openvt
-rwxr-xr-x 1 root root 13776 2009-04-10 08:51 /bin/openvt
lrwxrwxrwx 1 root root     4 2009-06-15 10:27 /bin/rnano -> nano
}}}

''顯示所有檔案, 包括子目錄''
{{{
$ ls .*
.bash_history  .bashrc    .fonts.cache-1  .recently-used.xbel  .sudo_as_admin_successful
.bash_logout   .esd_auth  .profile        .rnd                 .Xauthority

.:
apache-tomcat-6.0.20.zip  Desktop                  WebGoat-5.2.war
apache.zip                jdk-6u14-linux-i586.bin  第一名

..:
tobala

.adobe:
Flash_Player

.aptitude:
config
ls: cannot open directory .chewing: Permission denied

.dbus:
session-bus

.debtags:

.fontconfig:
4c599c202bc5c08e2d34565a40eac3b2-x86.cache-2
6d41288fd70b0be22e8c3a91e032eec0-x86.cache-2

.gconf:
apps

.gconfd:
saved_state

.gnome2:
accels  gedit

.gnome2_private:

.macromedia:
Flash_Player

.mozilla:
extensions  firefox

.scim:
config  global  pinyin  sys-tables
}}}




''參考文章''
1. Trash Problems and Solutions
http://ubuntuforums.org/showthread.php?t=898573

{{item1{垃圾桶在那裡 ?}}}
在 Ubuntu Desktop 10.04 桌面版中, 以 gksudo 開啟 終端機, 操作以下步驟 :

''尋找 Trash''
{{{
root@U104-Desktop:/home/student# find / -type d -name *Trash*
/home/student/.local/share/Trash
/root/.local/share/Trash                        (這是 root 的 Trash)
}}}

''檢視 root 垃圾桶內容''
{{{
root@U104-Desktop:/home/student# ls -al /root/.local/share/Trash/
總計 20
drwx------ 5 root root 4096 2010-08-02 13:20 .
drwx------ 5 root root 4096 2010-08-02 09:44 ..
drwx------ 2 root root 4096 2010-08-14 20:32 expunged
drwx------ 3 root root 4096 2010-08-15 10:15 files
drwx------ 2 root root 4096 2010-08-15 10:15 info

root@U104-Desktop:/home/student# ls -al /root/.local/share/Trash/files/
總計 12
drwx------ 3 root root 4096 2010-08-15 10:15 .
drwx------ 5 root root 4096 2010-08-02 13:20 ..
drwxr-xr-x 2 root root 4096 2010-08-15 10:15 未命名資料夾           (之前刪除的資料夾)
}}}

In older version of GNOME, the trash folder is in .Trash folder in your home directory (''~/.Trash''). But in current version (2.30) it is ''~/.local/share/Trash/''. It has two sub folders called files and info. The files folder contains the files deleted and info directory consists of meta data for each deleted file.

Here is an example:
{{{
$ cat ~/.local/share/Trash/info/style.org.css.trashinfo
[Trash Info]
Path=/home/blackgod/Desktop/style.org.css
DeletionDate=2010-06-01T09:59:18
}}}

{{item1{清除 root 垃圾桶}}}

''1. 更換 root 垃圾桶裡所有檔案的擁有人''
{{{
$ su -                (切換為 root)
# chown -R  student  /root/.local/share/Trash/
}}}

''2. 清除 root 垃圾桶''
{{{
# rm -rf /root/.local/share/Trash/*
# ls -al /root/.local/share/Trash
總計 8
drwx------ 2 root root 4096 2010-08-15 10:23 .
drwx------ 5 root root 4096 2010-08-02 09:44 ..
}}}

''[註]'' 如使用 sudo 刪除 root 垃圾桶, 因還是 root 身份, 所以 ''垃圾'' 又丟回 root 垃圾桶

<<toBalaNotes "trash">>

///%trash
//%/
以下實作是在 ''Ubuntu JeOS 8.04'' 系統中執行

{{item1{下載 nano 原始程式}}}
''$ wget http://www.nano-editor.org/dist/v2.2/nano-2.2.3.tar.gz''

{{item1{解壓縮 nano 的 tarball 檔}}}
''$ tar xzvf nano-2.2.3.tar.gz''

{{item1{檢視 nano-2.2.3 目錄內容}}}
''$ cd nano-2.2.3''

''$ dir''
{{{
ABOUT-NLS          config.h.in   depcomp      missing        README.SVN
aclocal.m4         config.rpath  doc          mkinstalldirs  src
AUTHORS            config.sub    INSTALL      nano.spec      THANKS
BUGS               configure     install-sh   nano.spec.in   TODO
ChangeLog          configure.ac  m4           NEWS           UPGRADE
ChangeLog.pre-2.1  COPYING       Makefile.am  po
config.guess       COPYING.DOC   Makefile.in  README
}}}

{{item1{檢查編譯環境及設定安裝目錄}}}

''$ sudo ./configure <nowiki>--</nowiki>prefix=/opt''
{{{
[sudo] password for tobala:
checking build system type... i686-pc-linux-gnu
checking host system type... i686-pc-linux-gnu
checking target system type... i686-pc-linux-gnu
                   :
checking for cc... no
checking for cl.exe... no
configure: error: in `/home/tobala/nano-2.2.3':
configure: error: no acceptable C compiler found in $PATH
See `config.log' for more details.
}}}
上述訊息指出並未找到 C 語言的翻譯器, 執行以下命令,安裝 gcc 及相關程式庫

''$ sudo apt-get install build-essential''
{{{
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
  binutils cpp cpp-4.2 dpkg-dev g++ g++-4.2 gcc gcc-4.2 libc6-dev libgdbm3
  libgomp1 libstdc++6-4.2-dev libtimedate-perl linux-libc-dev make patch perl
  perl-modules
Suggested packages:
  binutils-doc cpp-doc gcc-4.2-locales debian-keyring g++-multilib
  g++-4.2-multilib gcc-4.2-doc libstdc++6-4.2-dbg autoconf automake1.9 bison
  flex gcc-doc gcc-multilib gdb libtool manpages-dev gcc-4.2-multilib
  libgcc1-dbg libgomp1-dbg libmudflap0-4.2-dev libmudflap0-dbg glibc-doc
  libstdc++6-4.2-doc make-doc ed diff-doc libterm-readline-gnu-perl
  libterm-readline-perl-perl
Recommended packages:
  perl-doc
The following NEW packages will be installed:
  binutils build-essential cpp cpp-4.2 dpkg-dev g++ g++-4.2 gcc gcc-4.2
  libc6-dev libgdbm3 libgomp1 libstdc++6-4.2-dev libtimedate-perl
  linux-libc-dev make patch perl perl-modules
0 upgraded, 19 newly installed, 0 to remove and 1 not upgraded.
Need to get 19.2MB of archives.
After this operation, 74.2MB of additional disk space will be used.
Do you want to continue [Y/n]? yes
}}}

安裝後, 請再執行一次以下命令

''$ sudo ./configure <nowiki>--</nowiki>prefix=/opt''

這時會出現 curses 不存在的警告訊息, 請執行以下命令, 安裝 curses 套件

''$ sudo apt-get install libncurses5-dev''

{{item1{編譯 nano}}}

''$ sudo make''
{{{
checking whether to enable UTF-8 support... auto
checking whether to use slang... no
                        :
mv -f .deps/utils.Tpo .deps/utils.Po
gcc -DHAVE_CONFIG_H -I. -I.. -DLOCALEDIR=\"/opt/share/locale\" -DSYSCONFDIR=\"/opt/etc\"    -g -O2 -MT winio.o -MD -MP -MF .deps/winio.Tpo -c -o winio.o winio.c
mv -f .deps/winio.Tpo .deps/winio.Po
gcc  -g -O2   -o nano browser.o chars.o color.o cut.o files.o global.o help.o move.o nano.o prompt.o rcfile.o search.o text.o utils.o winio.o  -lncurses
make[2]: Leaving directory `/home/tobala/nano-2.2.3/src'
make[2]: Entering directory `/home/tobala/nano-2.2.3'
make[2]: Leaving directory `/home/tobala/nano-2.2.3'
make[1]: Leaving directory `/home/tobala/nano-2.2.3'
}}}

{{item1{安裝 nano}}}

''$ sudo make install''

{{item1{執行 nano}}}

''$ cd /opt''
''$ ./nano abc.txt''

''啟動後, 如下圖 :''

[img[img/nano.png]]

<<toBalaNotes "nano">>

{{item1{設定 nano 關鍵文字顏色}}}
本文網址 : http://how-to.wikia.com/wiki/How_to_use_syntax_highlighting_with_the_GNU_nano_text_editor

''Explaining how syntax highlight work''
You first need to specify a line with the name of the syntax and the files that you want to be highlighted by your syntax. Adding a line like :
{{{
syntax "c-file" "\.(c|h)$"
}}}
means that you want all the .c and .h files to be highlighted with the content that you specify after this line, with some regular expressions. For example, add the following line after the previous line to highlight all the integer numbers (positive or negative) in red :
{{{
color red "\<[-+]?([1-9][0-9]*|0)?\>"
}}}

在 /usr/share/nano 目錄中, 已存在各種檔案格式的語法設定檔, 例 java.nanorc, html.nanorc,...

''java.nanorc 內容''
{{{
## Here is an example for Java.
##
syntax "java" "\.java$"
color green "\<(boolean|byte|char|double|float|int|long|new|short|this|transient|void)\>"
color red "\<(break|case|catch|continue|default|do|else|finally|for|if|return|switch|throw|try|while)\>"
color cyan "\<(abstract|class|extends|final|implements|import|instanceof|interface|native|package|private|protected|public|static|strictfp|super|synchronized|throws|volatile)\>"
color red ""[^"]*""
color yellow "\<(true|false|null)\>"
color blue "//.*"
color blue start="/\*" end="\*/"
color brightblue start="/\*\*" end="\*/"
color ,green "[[:space:]]+$"
}}}


///%nano
//%/
{{item1{認識參數符號}}}
{{{
# nano argv.sh
echo $0
echo $1
echo $#                              (參數總數)
echo $@                             (所有參數內容, 參數間有空白)

# bash argv.sh a b c d 123

}}}

{{item1{參數處理}}}

''1. 處理第一個參數''
{{{
# nano hi.sh
echo "hi $1"

# chmod +x hi.sh

# ./hi.sh Chen
hi Chen
}}}

''2. 處理變動參數''
{{{
$  nano  myargv.sh
for  thing  in  “$@”
do
    echo  you typed  $thing.
done
}}}

''3. 顯示最後一個參數''
{{{
$ nano lastargv.sh
myargv="$@"
echo ${myargv##* }

$ bash lastargv.sh a b c
c
}}}

{{item1{檢查使用者密碼}}}
''參考文章''
1. Linux Shell script to add a user with a password to the system
http://www.cyberciti.biz/tips/howto-write-shell-script-to-add-user.html

{{{
#!/bin/bash

pd=$(perl -e 'print crypt($ARGV[0], "password")' $2)

grep $1:$pd /etc/shadow
echo $?
}}}

''執行''
{{{
$  ./checkpass.sh oc9root goforwin
oc9root:paAR9O92zgESU:15029:0:99999:7:::
0
}}}

<<toBalaNotes "1">>


///%1
//%/
''參考文章''
1. Password maintenance
http://www.ibm.com/developerworks/aix/library/au-chpasspwgen.html

{{item1{第一階段}}}
''1. 編輯帳號文字檔''
{{{
$ nano users.txt
a001:a001
a002:a002
a003:a003
}}}

''2. 顯示帳號文字檔內容''
{{{
$ u=$(cat users.txt)        # 會將多行文字, 變成一行, 然後存入 u
$ echo $u                                  
a001:a001 a002:a002 a003:a003
}}}

''3. 撰寫顯示帳號程式''
{{{
$ cd ~/bin

$ nano makeu.sh
#!/bin/bash
# Author : Sung-Ling Chen

s=$(cat users.txt)

for  thing  in $s
do
    echo $thing | cut -d: -f1
done

$ chmod +x makeu.sh
}}}

''4. 執行顯示帳號程式''
{{{
$ ./makeu.sh
a001
a002
a003
}}}

{{item1{第二階段}}}

''1. 修改 makeu.sh 程式 (顯示帳號與密碼)''
{{{
#!/bin/bash
# Author : Sung-Ling Chen

s=$(cat users.txt)

for  thing  in $s
do
    uname=$(echo $thing | cut -d: -f1)
    echo $uname

    upasswd=$(echo $thing | cut -d: -f2)
    echo $upasswd

done
}}}

''2. 執行 makeu.sh 程式''
{{{
$ ./makeu.sh 
a001
a001
a002
a002
a003
a003
}}}

{{item1{最終版 makeu.sh}}}

''$ nano makeu.sh''
{{{

#!/bin/bash
# Author : Sung-Ling Chen

[ ! -f users.txt ] && echo "file not found" && exit 1

s=$(cat users.txt)

for  us  in $s
do
    uname=${us%%:*}               # 因只有二個欄位, 所以可使用 %% 及 ##

    upasswd=${us##*:}

    useradd -m -s /bin/bash $uname
    echo "$uname:$upasswd" | chpasswd

done
}}}

''執行最終版 makeu.sh''
{{{
$ sudo ./makeu.sh                  # 一定要用 root 身份執行
}}}
<<toBalaNotes "1">>



///%1
//%/
{{item1{tail}}}
{{{
# tail  ~/.bash_history

# tail  -n3  ~/.bash_history
}}}

''檢視系統最新資訊''
''$ tail /var/log/syslog''
{{{
Aug 14 21:46:58 tobalaking dhclient: DHCPACK of 192.168.200.140 from 192.168.200.254
Aug 14 21:46:58 tobalaking dhclient: bound to 192.168.200.140 -- renewal in 698 seconds.
Aug 14 21:50:01 tobalaking /USR/SBIN/CRON[3117]: (root) CMD ([ -x /usr/sbin/update-motd ] && /usr/sbin/update-motd 2>/dev/null)
Aug 14 21:51:16 tobalaking init: tty2 main process ended, respawning
Aug 14 21:58:36 tobalaking dhclient: DHCPREQUEST of 192.168.200.140 on eth0 to 192.168.200.254 port 67
Aug 14 21:58:36 tobalaking dhcpd: DHCPREQUEST for 192.168.200.140 from 00:0c:29:c9:7d:5e via eth0: unknown lease 192.168.200.140.
Aug 14 21:58:36 tobalaking dhclient: DHCPACK of 192.168.200.140 from 192.168.200.254
Aug 14 21:58:36 tobalaking dhclient: bound to 192.168.200.140 -- renewal in 802 seconds.
Aug 14 22:00:01 tobalaking /USR/SBIN/CRON[3215]: (root) CMD ([ -x /usr/sbin/update-motd ] && /usr/sbin/update-motd hourly 2>/dev/null)
Aug 14 22:00:01 tobalaking /USR/SBIN/CRON[3218]: (root) CMD ([ -x /usr/sbin/update-motd ] && /usr/sbin/update-motd 2>/dev/null)
}}}
{{item1{head}}}
{{{
# head  -c 10  /etc/passwd


# head  -n 10  /etc/passwd


# head  file*
==> file1 <==
1111
2222
==> file2 <==
222
333
}}}

''練習 : 自定 netstat 命令, 執行時只顯示前 10 行''

<<toBalaNotes "text">>

{{item1{split}}}

{{op1{1. 切割大檔}}}
{{{
# ls -lh
total 120M
-rw-r--r-- 1 tobala tobala 6.1M 2009-06-18 01:18 apache-tomcat-6.0.20.zip
drwxr-xr-x 2 tobala tobala 4.0K 2009-06-16 15:57 Desktop
-rwxr-xr-x 1 tobala tobala  78M 2009-06-18 01:45 jdk-6u14-linux-i586.bin
-rw-r--r-- 1 tobala tobala  36M 2009-06-18 19:45 WebGoat-5.2.war

# split -b 2m apache-tomcat-6.0.20.zip xyz

# ls -lh
total 126M
-rw-r--r-- 1 tobala tobala 6.1M 2009-06-18 01:18 apache-tomcat-6.0.20.zip
drwxr-xr-x 2 tobala tobala 4.0K 2009-06-16 15:57 Desktop
-rwxr-xr-x 1 tobala tobala  78M 2009-06-18 01:45 jdk-6u14-linux-i586.bin
-rw-r--r-- 1 tobala tobala  36M 2009-06-18 19:45 WebGoat-5.2.war
-rw-r--r-- 1 tobala tobala 2.0M 2009-08-03 23:24 xyzaa
-rw-r--r-- 1 tobala tobala 2.0M 2009-08-03 23:24 xyzab
-rw-r--r-- 1 tobala tobala 2.0M 2009-08-03 23:24 xyzac
-rw-r--r-- 1 tobala tobala  86K 2009-08-03 23:24 xyzad
}}}

{{op1{2. 合併小檔}}}
{{{
# cat xyz* > apache.zip   (cat 會連續將 xyzaa, xyzab, xyzac,xyzad 內容輸出到 apache.zip)
# ls -lh
total 132M
-rw-r--r-- 1 tobala tobala 6.1M 2009-06-18 01:18 apache-tomcat-6.0.20.zip
-rw-r--r-- 1 tobala tobala 6.1M 2009-08-03 23:32 apache.zip
drwxr-xr-x 2 tobala tobala 4.0K 2009-06-16 15:57 Desktop
-rwxr-xr-x 1 tobala tobala  78M 2009-06-18 01:45 jdk-6u14-linux-i586.bin
-rw-r--r-- 1 tobala tobala  36M 2009-06-18 19:45 WebGoat-5.2.war
-rw-r--r-- 1 tobala tobala 2.0M 2009-08-03 23:24 xyzaa
-rw-r--r-- 1 tobala tobala 2.0M 2009-08-03 23:24 xyzab
-rw-r--r-- 1 tobala tobala 2.0M 2009-08-03 23:24 xyzac
-rw-r--r-- 1 tobala tobala  86K 2009-08-03 23:24 xyzad
}}}


///%text
//%/
''Step 1 :''
{{{
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install build-essential libtool e2fslibs-dev autoconf automake autotools-dev m4 e2fslibs e2fsprogs

wget http://sourceforge.net/projects/extundelete/files/extundelete/0.2.0/extundelete-0.2.0.tar.bz2/download

tar -xvjf extundelete-0.2.0.tar.bz2
cd extundelete-0.2.0
./autogen.sh
./configure
make
sudo make install
}}}

''Step 1a : (Alternative)''

If you want to generate a debian installable file instead of install from source, you can use this step.
{{{
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install build-essential libtool e2fslibs-dev autoconf automake autotools-dev m4 e2fslibs e2fsprogs checkinstall

wget http://sourceforge.net/projects/extundelete/files/extundelete/0.2.0/extundelete-0.2.0.tar.bz2/download

tar -xvjf extundelete-0.2.0.tar.bz2
cd extundelete-0.2.0
./autogen.sh
./configure
make
sudo checkinstall
}}}

Follow the instruction on screen to complete the debian executable file generation.
{{{
sudo dpkg -i extundelete_0.2.0-1_amd64.deb
or
sudo dpkg -i extundelete_0.2.0-1_i386.deb
}}}

''Step 2 :''

Usage :
{{{
Help -
extundelete --help

To undelete test.png file at /dev/sda3 and /home/samiux -
extundelete /dev/sda3 --restore-file /home/samiux/test.png

To undelete test directory at /dev/sda3 and /home/samiux -
extundelete /dev/sda3 --restore-directory /home/samiux/test

To undelete all files and directories at /dev/sda3 -
extundelete /dev/sda3 --restore-all
}}}
<<toBalaNotes "1">>


///%1
//%/
{{item1{管理程式目錄架構}}}

''編寫程式之前, 請先實作以下目錄架構''
{{{
oc99.98
├── bin
│ └── lib
├── conf
└── lib
}}}

{{item1{撰寫命令的安裝程式}}}

此程式負責安裝 fping, tree 及 expect 這三個命令
{{{
# cat ./lib/inscmd.sh
#!/bin/bash

[ "$USER" != "root" ] && echo "need root" && exit 1

cmd='fping tree expect'

for c in $cmd
do
    which $c &>/dev/null
    if [ "$?" != "0" ]; then
       echo -n "安裝 $c "
       apt-get -y install $c &>/dev/null
       if [ "$?" == "0" ]; then
         echo "完成"
       else
         echo "失敗"
       fi
    fi
done
}}}

{{item1{檢測線上主機}}}

''1.編寫 Network ID 設定檔''
{{{
$ cd ~/oc99.98/

$ nano conf/netid.conf
72.30.100.0/24
172.30.66.0/24
172.30.99.0/24
}}}

''2. 撰寫簡易測通程式''
{{{
$ nano checknid.sh
#!/bin/bash

[ "$USER" != "root" ] && echo "need root" && exit 1

# 安裝 fping 命令
fping -v &>/dev/null
if [ "$?" != "0" ];then
   apt-get install fping &>/dev/null
   [ "$?" != "0" ] && echo "fping can not install" && exit 1
   echo "fping ok"
fi

# 取出測通的 Network ID
nid=$(cat "$HOME/oc99.98/conf/netid.conf" | fmt -u)

# 開始測通網路
for s in $nid
do
    echo "$s checking"
    echo "---------------------------------"
    fping -c 1 -g -q $s &> "/tmp/${s%/*}.chk"
    grep "min/avg/max" "/tmp/${s%/*}.chk"
    echo ""   
done

exit 0
}}}

<<toBalaNotes "1">>

{{item1{檢測主機已安裝網路服務 (ssh, http, smb,..)}}}

''1. 撰寫檢測程式''
{{{
$ nano checknid.sh
#!/bin/bash

[ "$USER" != "root" ] && echo "need root" && exit 1

[ ! -f /usr/bin/fping ] && echo "apt-get install fping" && exit 1

nid=$(cat "$HOME/oc99.98/conf/netid.conf" | fmt -u)
echo ""
for s in $nid
do
    echo "$s scanning"
    echo "---------------------------------"
    fping -c 1 -g -q $s &> "/tmp/${s%/*}.chk"
    nip=$(grep "min/avg/max" "/tmp/${s%/*}.chk" | cut -d' ' -f1 | fmt -u)

    for ip in $nip
    do
       echo -n "$ip "

       nc -w 2 $ip 22 &>/dev/null
       [ "$?" == "0" ] && echo -n "ssh "

       nc -w 2 $ip 80 &>/dev/null
       [ "$?" == "0" ] && echo -n "www "

       nc -w 2 $ip 445 &>/dev/null
       [ "$?" == "0" ] && echo -n "smb"

       echo "" 
    done
    echo ""
done

exit 0
}}}

''2. 執行結果''
{{{
$ sudo ./checknid.sh

172.30.100.0/24 scanning
---------------------------------
172.30.100.1 ssh 
172.30.100.2 ssh 
172.30.100.5 ssh 
172.30.100.6 ssh 
172.30.100.10 ssh 
172.30.100.254 ssh 

172.30.66.0/24 scanning
---------------------------------
172.30.66.5 ssh 
172.30.66.10 smb
172.30.66.254 ssh 

172.30.99.0/24 scanning
---------------------------------
172.30.99.5 ssh 
172.30.99.10 smb
172.30.99.254 ssh 
}}}

<<toBalaNotes "2">>

{{item1{以網頁格式顯示檢測結果}}}

''1. 撰寫檢測程式''
{{{
$ nano checknid.sh

#!/bin/bash

[ "$USER" != "root" ] && echo "need root" && exit 1

# 安裝 fping 命令
. ./lib/inscmd.sh

echo ""
echo "<html>"
echo -e "<head>\n<link rel=stylesheet type='text/css' href='netid.css'>\n</head>"
echo "<body>"

if [ "$#" -gt 0 ]; then
   nid="$@"
else
   nid=$(cat "$HOME/oc99.98/conf/netid.conf" | fmt -u)
fi

echo ""
for s in $nid
do
    echo -e "<div id='${s%/*}'>$s</div>\n<ol>"
    fping -c 1 -g -q $s &> "/tmp/${s%/*}.chk"
    nip=$(grep "min/avg/max" "/tmp/${s%/*}.chk" | cut -d' ' -f1 | fmt -u)

    for ip in $nip
    do
       echo -n "<li>$ip "

       nc -w 2 $ip 22 &>/dev/null
       [ "$?" == "0" ] && echo -n "ssh "

       nc -w 2 $ip 80 &>/dev/null
       [ "$?" == "0" ] && echo -n "www "

       nc -w 2 $ip 445 &>/dev/null
       [ "$?" == "0" ] && echo -n "smb"

       echo ""
    done
    echo -e "</ol>\n"
done

echo -e "</body>\n</html>"

exit 0
}}}

''2. 執行命令''
{{{
$ ./checknid.sh                   (使用 conf/netid.conf)

      or

$ ./checknid.sh 140.137.214.0/24    (使用參數)
}}}

''3. 執行結果''
{{{
<html>
<head>
<link rel=stylesheet type='text/css' href='netid.css'>
</head>
<body>

<div id='172.30.100.0'>172.30.100.0/24</div>
<ol>
<li>172.30.100.1 ssh www smb
<li>172.30.100.2 ssh
<li>172.30.100.5 ssh
<li>172.30.100.254 ssh
</ol>

<div id='172.30.66.0'>172.30.66.0/24</div>
<ol>
<li>172.30.66.5 ssh
<li>172.30.66.10 smb
<li>172.30.66.254 ssh
</ol>

</body>
</html>
}}}

''[註]'' 可設計 netid.css 來強化網頁的版面
<<toBalaNotes "3">>

///%1
//%/

///%2
//%/

///%3
//%/
''參考文章''
1. Designing Simple front ends with dialog/Xdialog
http://linuxgazette.net/101/sunil.html
2. Dialog: An Introductory Tutorial
http://www.linuxjournal.com/article/2807?page=0,0
3. dialog
http://lcorg.blogspot.com/2010/03/dialog.html
4. whiptail man page
http://manpages.ubuntu.com/manpages/lucid/man1/whiptail.1.html
5. whiptail
http://www.weask.us/entry/bash-scripts-whiptail-file-select
6. "Colorizing" Scripts
http://www.tldp.org/LDP/abs/html/colorizing.html

{{op1{文字顯示}}}
The simplest, and perhaps most useful ANSI escape sequence is ''bold text,'' \033[1m ... \033[0m. The \033 represents an escape, the ''[1'' turns on the bold attribute, while the ''[0'' switches it off. The ''m'' terminates each term of the escape sequence. 
{{{
$ echo -e "\033[1mThis is bold text.\033[0m"
This is bold text.
}}}

A similar escape sequence switches on the ''underline'' attribute (on an rxvt and an aterm).
{{{
$ echo -e "\033[4mThis is underlined text.\033[0m"
}}}

''[註]'' With an echo, the ''-e option'' enables the escape sequences.
	
{{op1{文字顏色}}}
Other escape sequences change the text and/or background color.
{{{
bash$ echo -e '\E[34;47mThis prints in blue.'; tput sgr0


bash$ echo -e '\E[33;44m'"yellow text on blue background"; tput sgr0


bash$ echo -e '\E[1;33;44m'"BOLD yellow text on blue background"; tput sgr0
}}}

''[註]'' It's usually advisable to set the bold attribute for light-colored foreground text. The ''tput sgr0'' restores the terminal settings to normal. Omitting this lets all subsequent output from that particular terminal remain blue.

''[註]'' Since tput sgr0 fails to restore terminal settings under certain circumstances, echo -ne \E[0m may be a better choice.
      
{{op1{文字定址}}}
{{{
$ nano scr01
clear
echo -ne "\033[10;10f Hi Chen : "
read
}}}

''練習 :'' 如何將上面程式的字串變粗體 ? 

''程式範例 : 簡易選單系統''
{{{
#!/bin/bash
clear

function outputMenu {
echo "[1] edit file"
echo "[2] quit"

echo ""
echo -ne "choice : "
read USERCHOICE
clear

case $USERCHOICE in
        "1") nano $oc9conf;;
        "2")
            echo -n "y / n ? "
            read -e ans
            [ "$ans" == "y" ] && exit 0
            echo ""
            ;;
        *) echo "Unknown $USERCHOICE";;
esac
}

while [ 1 ]; do
   clear

   outputMenu

   echo ""
   echo -ne "return to main menu  ... "
   read
done
}}}

<<toBalaNotes "display">>

''程式範例 : 連絡清單''
{{{
#!/bin/bash
# ex30a.sh: "Colorized" version of ex30.sh.
#            Crude address database


clear                                   # Clear the screen.

echo -n "          "
echo -e '\E[37;44m'"\033[1mContact List\033[0m"
                                        # White on blue background
echo; echo
echo -e "\033[1mChoose one of the following persons:\033[0m"
                                        # Bold
tput sgr0                               # Reset attributes.
echo "(Enter only the first letter of name.)"
echo
echo -en '\E[47;34m'"\033[1mE\033[0m"   # Blue
tput sgr0                               # Reset colors to "normal."
echo "vans, Roland"                     # "[E]vans, Roland"
echo -en '\E[47;35m'"\033[1mJ\033[0m"   # Magenta
tput sgr0
echo "ones, Mildred"
echo -en '\E[47;32m'"\033[1mS\033[0m"   # Green
tput sgr0
echo "mith, Julie"
echo -en '\E[47;31m'"\033[1mZ\033[0m"   # Red
tput sgr0
echo "ane, Morris"
echo

read person

case "$person" in
# Note variable is quoted.

  "E" | "e" )
  # Accept upper or lowercase input.
  echo
  echo "Roland Evans"
  echo "4321 Flash Dr."
  echo "Hardscrabble, CO 80753"
  echo "(303) 734-9874"
  echo "(303) 734-9892 fax"
  echo "revans@zzy.net"
  echo "Business partner & old friend"
  ;;

  "J" | "j" )
  echo
  echo "Mildred Jones"
  echo "249 E. 7th St., Apt. 19"
  echo "New York, NY 10009"
  echo "(212) 533-2814"
  echo "(212) 533-9972 fax"
  echo "milliej@loisaida.com"
  echo "Girlfriend"
  echo "Birthday: Feb. 11"
  ;;

# Add info for Smith & Zane later.

   * )
   # Default option.	  
   # Empty input (hitting RETURN) fits here, too.
   echo
   echo "Not yet in database."
  ;;

esac

tput sgr0                               # Reset colors to "normal."

echo

exit 0
}}}


{{item1{Discover tput}}}
本文網址 : http://www.ibm.com/developerworks/aix/library/au-learningtput/index.html

''What is tput?''
The tput command initializes and manipulates your terminal session through the terminfo database. Using tput, you can alter several terminal capabilities, such as moving or altering the cursor, changing text properties, and clearing specific areas of the terminal screen.

''Command-line introduction to tput''
The tput command, like most commands in UNIX, can be used either at your shell command line or inside a shell script. To gain a better understanding of tput, this article starts with the command line, and then continues into shell script examples.

''Cursor attributes''
Moving the cursor or altering its attributes can be helpful in UNIX shell scripts or at the command line. There may be times when you're required to enter sensitive information, such as a password, or enter information in two different areas of the screen. Using tput can help you in such conditions.

''Moving the cursor''
Moving the cursor’s position on the respective device is easily done with tput. Using the cup option, or cursor position, in tput, you can move the cursor to any X or Y coordinates in the device's rows and columns. The top left coordinates of the device are 0,0.

To move the cursor to the fifth column (X) and the first row (Y) on a device, simply execute tput cup 5 1. Another example would be tput cup 23 45, which would move the cursor to the forty-fifth row in the twenty-third column.

''Moving the cursor and displaying information''
Another useful cursor position trick is to move the cursor, execute a command to display information, and then return to the previous cursor location:

(tput sc ; tput cup 23 45 ; echo “Input from tput/echo at 23/45” ; tput rc)

Let’s break down the subshell commands:
{{{
tput sc
}}}

The current cursor location must be saved first. To save the current cursor position, include the sc option, or "save cursor position."
{{{
tput cup 23 45
}}}

After the cursor location has been saved, the cursor coordinates will be moved to 23,45.
{{{
echo “Input from tput/echo at 23/45”
}}}

Display information to stdout.
{{{
tput rc
}}}

When the information has been displayed, the cursor must return to the original location that was saved with tput sc. To return the cursor to its last saved location, include the rc option, or "restore cursor position."

Note: Because this article details command-line execution of tput first, it would be cleaner for you to execute the commands in your own subshell rather than executing each command separately and showing a prompt before each command execution.

''Altering the cursor's attributes''

When displaying data to a device, there are times when you don't want to see the cursor. Turning the cursor invisible creates a cleaner look when data is scrolling across the screen. To make the cursor invisible, use the civis option (for example, tput civis). When the data has been completely displayed, you can make the cursor visible again by using the cnorm option.

''Text attributes''
Changing how text is shown can bring attention to a set of words in a menu or alert users to something important. You can change text attributes such as making the text bold, placing an underline under the text, changing the background and foreground colors, as well as reversing the color scheme.

To change the color of the text, use the setb option for setting the background color and the setf option for setting the foreground color along with the number of the color assigned in the terminfo database. The following numbers and colors are typically assigned but may vary from each UNIX system:
{{{
* 0: Black
* 1: Blue
* 2: Green
* 3: Cyan
* 4: Red
* 5: Magenta
* 6: Yellow
* 7: White
}}}

Executing these sample commands changes the background color to yellow and the foreground to red:
{{{
tput setb 6
tput setf 4
}}}

To reverse the current color scheme, simply execute tput rev.

Sometimes, adding color to text isn't enough, or you would rather draw the user's attention another way. Two ways to accomplish this would be to set the text to bold with underline.

To change the text to be bold, use the bold option. To begin underlining, use the smul option. When you're finished displaying the underlined text, use the rmul option.

<<toBalaNotes "2">>

{{item1{Using whiptail}}}
本文網址 : http://en.wikibooks.org/wiki/Bash_Shell_Scripting

Whiptail is a program that allows shell scripts to display dialog boxes to the user for informational purposes, or to get input from the user in a friendly way. Whiptail is included by default on Debian.
{{{
From the Linux Dictionary: whiptail is a "dialog" replacement using newt instead of ncurses.
From its README: whiptail is designed to be drop-in compatible with dialog(1), but has less features: some dialog boxes are not implemented, such as tailbox, timebox, calendarbox, etc.
}}}
A simple type of dialog box in Whiptail is the info box. This shows a dialog box containing text to the user.
{{{
whiptail --title "Example Dialog" --infobox "This is an example of an info box." 8 78
}}}
In the example above, the value of &#8722;-title is displayed at the top of the dialog box. The first argument to &#8722;-infobox is the dialog box text which is shown beneath the title. The next two arguments specify the height and width of the dialog box. The width is set to 78 as most terminals will be at least 80 columns or more.

A message box is very similar to an info box, except that it waits for the user to hit the OK button. Usage is similar to the info box:
{{{
whiptail --title "Example Dialog" --msgbox "This is an example of a message box. You must hit OK to continue." 8 78
}}}

The simplest way to get input from the user is via a Yes/no box. This displays a dialog with two buttons labelled Yes and No.
{{{
whiptail --title "Example Dialog" --yesno "This is an example of a yes/no box." 8 78
 
exitstatus=$?
if [ $exitstatus = 0 ]; then
    echo "User selected Yes."
else
    echo "User selected No."
fi
 
echo "(Exit status was $exitstatus)"
}}}

Whenever you want to present a list of options to the user, whiptail has several dialog types to choose from.

A menu should be used when you want the user to select one option from a list, such as for navigating a program.
{{{
whiptail --title "Menu example" --menu "Choose an option" 20 78 16 \
"<-- Back" "Return to the main menu." \
"Add User" "Add a user to the system." \
"Modify User" "Modify an existing user." \
"List Users" "List all users on the system." \
"Add Group" "Add a user group to the system." \
"Modify Group" "Modify a group and its list of members." \
"List Groups" "List all groups on the system."
}}}
The values given to &#8722;-menu are:

    * The text describing the menu ("Choose an option")
    * The height of the dialog (20)
    * The width of the dialog (78)
    * The height of the menu list (16)

The rest of the values are a list of menu options in the format tag item, where tag is the name of the option which is printed to stderr when selected, and item is the description of the menu option.

If you are presenting a very long menu and want to make best use of the available screen, you can calculate the best box size by.
{{{
eval `resize`
whiptail ... $LINES $COLUMNS $(( $LINES - 8 )) ...
}}}

At some point, you will want to present options to the user which would not be appropriate to place in a menu.

A check list allows a user to select one or more options from a list.
{{{
whiptail --title "Check list example" --checklist \
"Choose user's permissions" 20 78 16 \
"NET_OUTBOUND" "Allow connections to other hosts" ON \
"NET_INBOUND" "Allow connections from other hosts" OFF \
"LOCAL_MOUNT" "Allow mounting of local devices" OFF \
"REMOTE_MOUNT" "Allow mounting of remote devices" OFF
}}}
When the user comfirms their selections, a list of the choices is printed to stderr.

A radio list is a dialog where the user can select one option from a list. The difference between a radio list and a menu is that the user selects an option (using the space bar in whiptail) and then comfirms that choice by hitting OK.
{{{
#!/bin/bash
{
    for ((i = 0 ; i <= 100 ; i+=30)); do
        sleep 1
        echo $i
    done
} | whiptail --gauge "Please wait" 5 50 0
}}}
<<toBalaNotes "3">>


///%1
//%/

///%display
//%/

///%2
//%/

///%3
//%/
''參考文章''
1. A System Monitoring Tool Primer
http://certcities.com/editorial/columns/story.asp?EditorialsID=413

When you're the system administrator, you must keep an eye on how well your Linux system is performing by looking at information such as:
{{{
* Central Processing Unit (CPU) usage
* Physical memory usage
* Virtual memory (swap-space) usage
* Hard drive usage
}}}
Linux comes with a number of utilities that can be used to monitor one or more of these performance parameters. The following sections introduce a few of these utilities and show how to understand the information presented by them.

{{item1{Using the Top Utility}}}
To view the top CPU processes - the ones that use most of the CPU time - you can use the text mode top utility. To start that utility, type ''top'' in a terminal window (or text console). The top utility then displays a text screen listing the current processes arranged in the order of CPU usage, along with various other information, such as memory and swap-space usage. The top utility updates the display every five seconds. If you keep top running in a window, you can continually monitor the status of your Linux system. To quit top, press Q, Ctrl+C or close the terminal window.

''$ top''
{{{
top - 23:34:22 up 10:58,  2 users,  load average: 0.09, 0.05, 0.04
Tasks: 166 total,   2 running, 163 sleeping,   1 stopped,   0 zombie
Cpu(s):  0.8%us,  2.3%sy,  0.0%ni, 96.9%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   4019588k total,  2504716k used,  1514872k free,    93376k buffers
Swap:  5116660k total,        0k used,  5116660k free,  1604772k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
   37 root      25   5     0    0    0 S    4  0.0  17:04.85 ksmd
 1156 root      20   0 83276  14m 3276 S    1  0.4   1:07.56 libvirtd
 1278 root      20   0 79376  31m  13m S    0  0.8   1:39.92 Xorg
 1458 student   20   0 89624 9612 7380 S    0  0.2   0:02.04 gnome-settings-
 1767 student   20   0  2544 1232  924 R    0  0.0   0:00.02 top
 9452 root      20   0  144m  37m  17m S    0  1.0   1:52.62 python
 9724 root      20   0  599m 530m 2888 S    0 13.5   3:19.05 kvm
    1 root      20   0  2800 1732 1224 S    0  0.0   0:01.13 init
    2 root      20   0     0    0    0 S    0  0.0   0:00.00 kthreadd
    3 root      RT   0     0    0    0 S    0  0.0   0:00.00 migration/0
    4 root      20   0     0    0    0 S    0  0.0   0:00.00 ksoftirqd/0
    5 root      RT   0     0    0    0 S    0  0.0   0:00.00 watchdog/0
    6 root      RT   0     0    0    0 S    0  0.0   0:00.00 migration/1
    7 root      20   0     0    0    0 S    0  0.0   0:00.02 ksoftirqd/1
    8 root      RT   0     0    0    0 S    0  0.0   0:00.00 watchdog/1
    9 root      20   0     0    0    0 S    0  0.0   0:00.28 events/0
   10 root      20   0     0    0    0 S    0  0.0   0:00.00 events/1
}}}

The first five lines of the output screen provide summary information about the system, arranged in the following order:
{{{
* The first line shows the current time, how long the system has been up, how many users are logged in and three load averages  --  the average number of processes ready to run during the last 1, 5, and 15 minutes.
* The second line lists the total number and status of processes.
* The third line shows CPU usage -- what percentage of CPU time is used by user processes, what percentage by system (kernel) processes, and during what percentage of time the CPU is idle.
* The fourth line shows how the physical memory is being used -- the total amount, how much is used, how much is free and how much is allocated to buffers (for example, readings from the hard drive).
* The fifth line shows how the virtual memory (or swap space) is being used -- the total amount of swap space, how much is used, how much is free, and how much is being cached.
}}}
The table that appears below lists information about the current processes, arranged in decreasing order by amount of CPU time used. It also summarizes the meanings of the column headings in the table the top displays.

Meanings of Column Headings in top Utility's Output
|''Heading''|''Meaning''|
|PID|The process ID of the process|
|USER|Username of the running process|
|PR|Priority of the process|
|NI|Nice value of the process - the value ranges from -20 (highest priority) to 19 (lowest priority) and the default is 0. (The nice value represents the relative priority of the process. The higher the value the lower the priority and the nicer the process - because it yields to other processes)|
|VIRT|The total amount  (in kilobytes) of virtual memory used by the process|
|RES|Total physical memory used by a task (typically shown in kilobytes, with an m suffix indicating megabytes)|
|SHR|Amount of shared memory used by process|
|S|State of the process (S for sleeping, D for uninterruptible sleep, R for running, Z for zombies  -  processes that should be dead but are still running  -  or T for stopped)|
|%CPU|Percentage of CPU time used since last screen update|
|%MEM|Percentage of physical memory used by the process|
|TIME+|Total CPU time the process has used since it started|
|COMMAND|Shortened form of the command that started the process|

{{item1{Using the Uptime Command}}}
Use the uptime command to get a summary of the system's state by typing the following command:

''$ uptime''

It displays output similar to the following:
{{{
15:03:21 up 32 days, 57 min, 3 users, load average: 0.13, 0.23, 0.27
}}}
This output shows the current time, how long the system has been up, the number of users and (finally) the three load averages  -  the average number of processes that were ready to run in the past 1, 5, and 15 minutes. Load averages greater than 1 imply that many processes are competing for CPU time simultaneously.

The load averages give you an indication of how busy the system is.

{{item1{Using the Vmstat Utility}}}
Receive summary information about the overall system usage with the vmstat utility. To view system usage information averaged over 5-second intervals, type the following command (the second argument indicates the total number of lines of output vmstat displays):

''$ vmstat 5 8''

{{{
procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in    cs us sy id wa
 0  0  31324   4016  18568 136004    1    1    17    16    8   110 33  4 61  1
 0  1  31324   2520  15348 139692    0    0  7798   199 1157   377  8  8  6 78
 1  0  31324   1584  12936 141480    0   19  5784   105 1099   437 12  5  0 82
 2  0  31324   1928  13004 137136    7    0  1586   138 1104   561 43  6  0 51
 3  1  31324   1484  13148 132064    0    0  1260    51 1080   427 50  5  0 46
 0  0  31324   1804  13240 127976    0    0  1126    46 1082   782 19  5 47 30
 0  0  31324   1900  13240 127976    0    0     0     0 1010   211  3  1 96  0
 0  0  31324   1916  13248 127976    0    0     0    10 1015   224  3  2 95  0
}}}
The first line of output shows the averages since the last reboot. After that, vmstat displays the ''5-second'' average data seven more times, covering the next 35 seconds. The tabular output is grouped as six categories of information, indicated by the fields in the first line of output. The second line shows further details for each of the six major fields. You can interpret these fields 

Meaning of Fields in the vmstat Utility's Output

|''Field Name''|''Description''|
|procs|Number of processes and their types: ''r = processes waiting to run'', ''b = processes in uninterruptible sleep'', w = processes swapped out but ready to run|
|memory|Information about physical memory and swap-space usage (all numbers in kilobytes): swpd = virtual memory used, free = free physical memory, buff = memory used as buffers, cache = virtual memory that's cached|
|swap|Amount of swapping (the numbers are in kilobytes per second): si = amount of memory swapped in from disk, so = amount of memory swapped to disk|
|io|Information about input and output. (The numbers are in blocks per second where the block size depends on the disk device.) bi = rate of blocks sent to disk, bo = rate of blocks received from disk|
|system|Information about the system: in = number of interrupts per second (including clock interrupts), cs = number of context switches per second  - - how many times the kernel changed which process was running|
|cpu|Percentages of CPU time used: us = percentage of CPU time used by user processes, sy = percentage of CPU time used by system processes, id = percentage of time CPU is idle, wa = time spent waiting for input or output (I/O)|

In the vmstat utility's output, high values in the si and so fields indicate too much swapping (the copying of information between physical memory and the virtual memory on the hard drive). High numbers in the bi and bo fields indicate too much disk activity.

{{item1{Checking Disk Performance and Disk Usage}}}
Linux comes with the /sbin/hdparm program that can be used to control IDE or ATAPI hard drives that are common on most PCs. One feature of the hdparm program is to use the ''-t option'' to determine the rate at which data is read from the disk into a buffer in memory. For example, here's the result of typing /sbin/hdparm -t /dev/hda on one system:
/dev/hda:

''sudo hdparm -t /dev/sda''
{{{
/dev/sda:
 Timing buffered disk reads:  322 MB in  3.00 seconds = 107.26 MB/sec
}}}
The command requires the IDE drive's device name (/dev/hda for the first hard drive and /dev/hdb for the second hard drive) as an argument. If you have an IDE hard drive, you can try this command to see how fast data is read from your system's disk drive.

To display the space available in the currently mounted file systems, use the df command. If you want a more readable output from df, type the following command:
{{{
df -h
}}}
Here's a typical output from this command:
{{{
檔案系統            大小  已用  可用   已用% 掛載點
/dev/sda1            39G  3.0G   34G   9%    /
none                  2.0G  284K  2.0G   1%   /dev
none                  2.0G  1.3M  2.0G   1% /dev/shm
none                  2.0G  276K  2.0G   1% /var/run
none                  2.0G     0    2.0G   0% /var/lock
none                  2.0G     0    2.0G   0% /lib/init/rw
none                   39G  3.0G   34G   9% /var/lib/ureadahead/debugfs
student@U104-Desktop:~$

}}}
As As this example shows, the -h option causes the df command to show the sizes in gigabytes (G) and megabytes (M).

To check the disk space being used by a specific directory, use the du command and specify the -h option to view the output in kilobytes (K) and megabytes (M), as shown in the following example:
{{{
du -h /var/log
}}}
Here's a typical output of that command:
{{{
152K    /var/log/cups
4.0K    /var/log/vbox
4.0K    /var/log/httpd
508K    /var/log/gdm
4.0K    /var/log/samba
8.0K    /var/log/mail
4.0K    /var/log/news/OLD
8.0K    /var/log/news
4.0K    /var/log/squid
2.2M    /var/log
}}}
The du command displays the disk space used by each directory, and the last line shows the total disk space used by that directory. If you want to see only the total space used by a directory, use the ''-s option''. For example, type du -sh /home to see the space used by the /home directory. The command produces an output that looks like this:
{{{
89M     /home
}}}
<<toBalaNotes "mon">>


///%mon
//%/
''參考文章''
1. ssh + expect
http://ssorc.tw/rewrite.php/read-600.html
2. SSh username and password script 
http://www.linuxforums.org/forum/programming-scripting/24126-ssh-username-password-script.html
3. Expect 遠端關機 (遠端將 Windows 主機關機)
http://labs.ndhu.edu.tw/index.php/Expect_%E9%81%A0%E7%AB%AF%E9%97%9C%E6%A9%9F

{{item1{網管機器人引擎 - expect}}}
''The Expect Home Page'' : http://expect.sourceforge.net/

''1. 安裝 expect 套件''
{{{
$ sudo apt-get install expect
[sudo] password for student:
正在讀取套件清單... 完成
正在重建相依關係
正在讀取狀態資料... 完成
下列的額外套件將被安裝:
  tcl8.5
建議套件:
  expectk tclreadline
下列【新】套件將會被安裝:
  expect tcl8.5
升級 0 個,新安裝 2 個,移除 0 個,有 1 個未被升級。
需要下載 1,804kB 的套件檔。
此操作完成之後,會多佔用 4,940kB 的磁碟空間。
是否繼續進行 [Y/n]?
}}}

{{item1{執行遠端命令}}}
''1. 編輯 autossh.sh 的程式''
{{{
$ nano autossh.sh
#!/usr/bin/expect -f
set timeout 5

#example of getting arguments passed from command line..
#not necessarily the best practice for passwords though...
set server [lindex $argv 0]
set user [lindex $argv 1]
set pass [lindex $argv 2]
set cmd [lindex $argv 3]

# connect to server via ssh, login, and su to root
send_user "connecting to $server\n"
spawn ssh $user@$server

#login handles cases:
#   login with keys (no user/pass)
#   user/pass
#   login with keys (first time verification)
expect "yes/no" { send "yes\r" }
expect "password:" { send "$pass\r" }

expect {
   "$ " {}
   default {}
}
# run command
send "$cmd\r"

expect {
  default {}
}
#login out
send "exit\r"

expect {
  default {}
}
}}}

''2. 執行結果''
{{{
$ ./autossh 140.137.214.66 student student
connecting to 140.137.214.66
spawn ssh student@140.137.214.66
student@140.137.214.66's password:
Linux US1041NoBody 2.6.32-24-generic-pae #42-Ubuntu SMP Fri Aug 20 15:37:22 UTC 2010 i686 GNU/Linux
Ubuntu 10.04.1 LTS

Welcome to Ubuntu!
 * Documentation:  https://help.ubuntu.com/

  System information as of Thu Sep 30 02:28:23 CST 2010

  System load:  0.02              Processes:           65
  Usage of /:   22.6% of 3.71GB   Users logged in:     1
  Memory usage: 6%                IP address for lo:   127.0.0.1
  Swap usage:   0%                IP address for eth0: 140.137.214.66

  Graph this data and manage this system at https://landscape.canonical.com/

22 packages can be updated.
8 updates are security updates.

Last login: Thu Sep 30 01:55:45 2010
student@US1041NoBody:~$
student@US1041NoBody:~$ exit
logout
Connection to 140.137.214.66 closed.
}}}

{{item1{複製目錄資訊至遠端主機}}}

''1. 撰寫 autoscp.sh 程式''
{{{
$ cat lib/autoscp.sh
#!/usr/bin/expect -f
set timeout 5

#example of getting arguments passed from command line..
#not necessarily the best practice for passwords though...
set server [lindex $argv 0]
set user [lindex $argv 1]
set pass [lindex $argv 2]
set sdir [lindex $argv 3]
set tdir [lindex $argv 4]

# connect to server via ssh, login, and su to root
send_user "connecting to $server\n"
spawn scp -r $sdir $user@$server:$tdir

#login handles cases:
#   login with keys (no user/pass)
#   user/pass
#   login with keys (first time verification)
expect "yes/no" { send "yes\r" }
expect "password:" { send "$pass\r" }

expect {
  default {}
}
}}}

''2. 執行結果''
{{{
$ ./lib/autoscp.sh 172.30.66.5 student student /root/oc99.98/bin /home/student
connecting to 172.30.66.5
spawn scp -r /root/oc99.98/bin student@172.30.66.5:/home/student
student@172.30.66.5's password:
sysprep.sh                                                        100%  833     0.8KB/s   00:00
root@US104-100-NAT:~/oc99.98#
}}}

<<toBalaNotes "1">>

{{item1{expect-lite}}}
''The Expect-lite Home Page'' : http://expect-lite.sourceforge.net/

''expect-lite'' is an quick and easy command line automation tool.

Written in expect, it is designed to directly map an interactive terminal session into an automation script. expect-lite scripts use special character(s) at the beginning of each line to indicate the action. Basic expect-lite scripts can be created by simply cutting and pasting text from a terminal window into a script, and adding '>' '<' characters. No knowledge of expect is required!

Expect-lite is targeted at the verification testing environment, and will produce a Pass/Fail result at the end of the script. However, its use is not limited to this environment. 

{{item1{安裝 Expect-lite}}}
''1. 下載''
{{{
$ wget http://sourceforge.net/projects/expect-lite/files/expect-lite/expect-lite_3.7.1/expect-lite_3.7.1.tar.gz
}}}

''2. 複製 expect-lite 到 ~/bin''
{{{
$ tar xvfz expect-lite_3.7.1.tar.gz
$ cd expect-lite.proj/
$ cp expect-lite ~/bin/
}}}

''[註]'' 使用此命令, 必須先安裝 expect 套件, 安裝命令 sudo apt-get install expect

{{item1{Quick Start}}}

Expect-lite has many features which make it useful, and the documenation highlights those. But to start using expect-lite quickly, you require two items:
{{{
1. a script
2. a host 
}}}

Here is a quick script which you can paste into a file to test expect-lite, call it ''test.elt'' :
{{{
@5                       (time out 5 秒)
>ping -c 2 localhost
+$packet_rx=([0-9]+) received
>
>echo "Packets received are:$packet_rx"
}}}

The second item you require is a host to run your script against. Expect-lite is designed to log into a remote host and run your script, as if a person was typing the commands. However that may require setting up ssh keys and so forth, and this is the Quick Start section. Type the following to run the above script on your localhost:
{{{
expect-lite -c test.elt -r none
}}}

There should be output that looks similar to the following:
{{{

Warning: unable to locate Tclx package
Warning: Instant-Interact '^\' feature is disabled

Warning: Remote Host=none, using Localhost
spawn bash

 ==== Ping localhost and report result ====


[student@US1041NoBody:~/bin]$

Setting Expect Timeout to: 5


ping -c 2 localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.039 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.022 ms

--- localhost ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.022/0.030/0.039/0.010 ms
[student@US1041NoBody:~/bin]$
Assigned Var:packet_rx=2


[student@US1041NoBody:~/bin]$
[student@US1041NoBody:~/bin]$ echo "Packets received are:2"
Packets received are:2
[student@US1041NoBody:~/bin]$

##Overall Result: PASS
}}}
<<toBalaNotes "2">>

///%1
//%/

///%2
//%/

{{item1{lshw}}}
Ubuntu Server 內建此命令

''檢視所有硬體規格 (資訊比 hwinfo 命令清楚)''
{{{
# lshw -short
H/W path         Device      Class          Description
=======================================================
                             system         System Product Name
/0                           bus            P5Q-EM DO(BP)
/0/0                         memory         64KiB BIOS
/0/4                         processor      Intel(R) Core(TM)2 Duo CPU     E8400  @ 3.00GHz
/0/4/5                       memory         64KiB L1 cache
/0/4/6                       memory         6MiB L2 cache
/0/32                        memory         4GiB System Memory
/0/32/0                      memory         2GiB DIMM DDR2 Synchronous 800 MHz (1.2 ns)
/0/32/1                      memory         DIMM [empty]
/0/32/2                      memory         2GiB DIMM DDR2 Synchronous 800 MHz (1.2 ns)
/0/32/3                      memory         DIMM [empty]
/0/100                       bridge         4 Series Chipset DRAM Controller
/0/100/2                     display        4 Series Chipset Integrated Graphics Controller
/0/100/2.1                   display        4 Series Chipset Integrated Graphics Controller
/0/100/3                     communication  4 Series Chipset HECI Controller
/0/100/19        eth1        network        82567LM-3 Gigabit Network Connection
/0/100/1a                    bus            82801JD/DO (ICH10 Family) USB UHCI Controller #4
/0/100/1a.1                  bus            82801JD/DO (ICH10 Family) USB UHCI Controller #5
/0/100/1a.2                  bus            82801JD/DO (ICH10 Family) USB UHCI Controller #6
/0/100/1a.7                  bus            82801JD/DO (ICH10 Family) USB2 EHCI Controller #2
/0/100/1b                    multimedia     82801JD/DO (ICH10 Family) HD Audio Controller
/0/100/1d                    bus            82801JD/DO (ICH10 Family) USB UHCI Controller #1
/0/100/1d.1                  bus            82801JD/DO (ICH10 Family) USB UHCI Controller #2
/0/100/1d.2                  bus            82801JD/DO (ICH10 Family) USB UHCI Controller #3
/0/100/1d.7                  bus            82801JD/DO (ICH10 Family) USB2 EHCI Controller #1
/0/100/1e                    bridge         82801 PCI Bridge
/0/100/1e/0      eth0        network        RTL-8139/8139C/8139C+
/0/100/1f                    bridge         82801JDO (ICH10DO) LPC Interface Controller
/0/100/1f.2      scsi0       storage        82801JD/DO (ICH10 Family) 4-port SATA IDE Controller
/0/100/1f.2/0    /dev/sda    disk           1TB Hitachi HDT72101
/0/100/1f.2/0/1  /dev/sda1   volume         39GiB EXT4 volume
/0/100/1f.2/0/2  /dev/sda2   volume         4996MiB Linux swap volume
/0/100/1f.2/0/3  /dev/sda3   volume         24GiB Windows NTFS volume
/0/100/1f.2/1    /dev/cdrom  disk           DVD D  DH18D4S
/0/100/1f.3                  bus            82801JD/DO (ICH10 Family) SMBus Controller
/1                           power          Nikon Ultra Plus
/2                           power          To Be Filled By O.E.M.
}}}

''單獨檢視網卡資訊''
{{{
# lshw -class network
  *-network DISABLED
       description: Ethernet interface
       product: 82567LM-3 Gigabit Network Connection
       vendor: Intel Corporation
       physical id: 19
       bus info: pci@0000:00:19.0
       logical name: eth1
       version: 02
       serial: 00:26:18:08:f8:98
       capacity: 1GB/s
       width: 32 bits
       clock: 33MHz
       capabilities: pm msi bus_master cap_list ethernet physical tp 10bt 10bt-fd 100bt 100bt-fd 1000bt-fd autonegotiation
       configuration: autonegotiation=on broadcast=yes driver=e1000e driverversion=1.0.2-k2 firmware=0.4-3 latency=0 link=no multicast=yes port=twisted pair
       resources: irq:28 memory:fe9c0000-fe9dffff memory:fe9fa000-fe9fafff ioport:d880(size=32)
  *-network
       description: Ethernet interface
       product: RTL-8139/8139C/8139C+
       vendor: Realtek Semiconductor Co., Ltd.
       physical id: 0
       bus info: pci@0000:01:00.0
       logical name: eth0
       version: 10
       serial: 00:09:73:dd:ae:5b
       size: 100MB/s
       capacity: 100MB/s
       width: 32 bits
       clock: 33MHz
       capabilities: pm bus_master cap_list rom ethernet physical tp mii 10bt 10bt-fd 100bt 100bt-fd autonegotiation
       configuration: autonegotiation=on broadcast=yes driver=8139too driverversion=0.9.28 duplex=full latency=64 link=yes maxlatency=64 mingnt=32 multicast=yes port=MII speed=100MB/s
       resources: irq:16 ioport:e800(size=256) memory:febffc00-febffcff memory:f0000000-f000ffff(prefetchable)
}}}

{{item1{hwinfo}}}
''在 Ubuntu Server 10.04 - 64 位元系統, 請安裝 hwinfo 套件''
{{{
# apt-get install hwinfo
正在讀取套件清單... 完成
正在重建相依關係
正在讀取狀態資料... 完成
以下套件是被自動安裝進來的,且已不再會被用到了:
  libssl-dev
使用 'apt-get autoremove' 來將其移除。
下列的額外套件將被安裝:
  libhd16
下列【新】套件將會被安裝:
  hwinfo libhd16
升級 0 個,新安裝 2 個,移除 0 個,有 1 個未被升級。
需要下載 749kB 的套件檔。
此操作完成之後,會多佔用 2,114kB 的磁碟空間。
是否繼續進行 [Y/n]?y
下載:1 http://tw.archive.ubuntu.com/ubuntu/ lucid/universe libhd16 16.0-2 [703kB]
下載:2 http://tw.archive.ubuntu.com/ubuntu/ lucid/universe hwinfo 16.0-2 [46.9kB]
取得 749kB 用了 0s (971kB/s)
選取了原先未被選取的套件 libhd16。
(正在讀取資料庫 ... 系統目前共安裝了 61512 個檔案和目錄。)
正在解開 libhd16 (從 .../libhd16_16.0-2_amd64.deb)...
選取了原先未被選取的套件 hwinfo。
正在解開 hwinfo (從 .../hwinfo_16.0-2_amd64.deb)...
正在進行 man-db 的觸發程式 ...
正在設定 libhd16 (16.0-2) ...

正在設定 hwinfo (16.0-2) ...
正在進行 libc-bin 的觸發程式 ...
ldconfig deferred processing now taking place
}}}

''檢視主機的硬體規格''
{{{
root@US1041KVM:~# hwinfo --short
cpu:
                       Intel(R) Core(TM)2 Duo CPU     E8400  @ 3.00GHz, 2003 MHz
                       Intel(R) Core(TM)2 Duo CPU     E8400  @ 3.00GHz, 2003 MHz
keyboard:
  /dev/input/event4    Colorado USB Keyboard
mouse:
  /dev/input/mice      IBM USB Mouse
  /dev/input/mice      Macintosh mouse button emulation
graphics card:
                       Intel 4 Series Chipset Integrated Graphics Controller
                       Intel 4 Series Chipset Integrated Graphics Controller
sound:
                       Intel 82801JD/DO (ICH10 Family) HD Audio Controller
storage:
                       Floppy disk controller
                       Intel 82801JD/DO (ICH10 Family) 4-port SATA IDE Controller
network:
  eth1                 Intel 82567LM-3 Gigabit Network Connection
  eth0                 Realtek RT8139
network interface:
  lo                   Loopback network interface
  eth0                 Ethernet network interface
  eth1                 Ethernet network interface
  br0                  Ethernet network interface
  virbr2               Ethernet network interface
  virbr0               Ethernet network interface
disk:
  /dev/sda             Hitachi HDT72101
partition:
  /dev/sda1            Partition
  /dev/sda2            Partition
  /dev/sda3            Partition
cdrom:
  /dev/sr0             ATAPI DVD D  DH18D4S
usb controller:
                       Intel 82801JD/DO (ICH10 Family) USB UHCI Controller #4
                       Intel 82801JD/DO (ICH10 Family) USB UHCI Controller #5
                       Intel 82801JD/DO (ICH10 Family) USB UHCI Controller #6
                       Intel 82801JD/DO (ICH10 Family) USB2 EHCI Controller #2
                       Intel 82801JD/DO (ICH10 Family) USB UHCI Controller #1
                       Intel 82801JD/DO (ICH10 Family) USB UHCI Controller #2
                       Intel 82801JD/DO (ICH10 Family) USB UHCI Controller #3
                       Intel 82801JD/DO (ICH10 Family) USB2 EHCI Controller #1
bios:
                       BIOS
bridge:
                       Intel 4 Series Chipset DRAM Controller
                       Intel 82801 PCI Bridge
                       Intel 82801JDO (ICH10DO) LPC Interface Controller
hub:
                       Linux 2.6.32-24-server ehci_hcd EHCI Host Controller
                       Linux 2.6.32-24-server ehci_hcd EHCI Host Controller
                       Linux 2.6.32-24-server uhci_hcd UHCI Host Controller
                       Linux 2.6.32-24-server uhci_hcd UHCI Host Controller
                       Linux 2.6.32-24-server uhci_hcd UHCI Host Controller
                       Linux 2.6.32-24-server uhci_hcd UHCI Host Controller
                       Linux 2.6.32-24-server uhci_hcd UHCI Host Controller
                       Linux 2.6.32-24-server uhci_hcd UHCI Host Controller
memory:
                       Main Memory
unknown:
                       FPU
                       DMA controller
                       PIC
                       Timer
                       Keyboard controller
                       PS/2 Controller
                       Intel 4 Series Chipset HECI Controller
                       Intel 82801JD/DO (ICH10 Family) SMBus Controller
  /dev/ttyS0           16550A
  /dev/ttyS1           16550A
  /dev/input/event5    Colorado USB Keyboard
}}}

''單獨檢視記憶體資訊''
{{{
# hwinfo --memory                  ()
01: None 00.0: 10102 Main Memory
  [Created at memory.61]
  Unique ID: rdCR.CxwsZFjVASF
  Hardware Class: memory
  Model: "Main Memory"
  Memory Range: 0x00000000-0xf1630fff (rw)
  Memory Size: 3 GB + 768 MB
  Config Status: cfg=new, avail=yes, need=no, active=unknown
}}}

<<toBalaNotes "mem">>



///%mem
//%/
''參考文章''
1. 請教在 Bash 下有沒有工具可以做到像 getc 的工具 
http://www.study-area.org/phorum/index.php?topic=9553.0

{{{
getc()
{
oldstty=`stty -g`
stty raw -echo
eval $1=`dd bs=5 count=1  2>/dev/null`  
stty $oldstty
}
echo "press a key"
getc ans
echo "this is you type:"
echo $ans '+' ${ans#?}
echo "bye!"
}}}
<<toBalaNotes "1">>


///%1
//%/
{{item1{撰寫收集所有主機資訊的程式}}}
{{{
$ nano getnid.sh

#!/bin/bash

[ "$USER" != "root" ] && echo "need root" && exit 1

if [ "$#" -gt 0 ]; then
   nid="$@"
else
   nid=$(cat "$HOME/oc99.98/conf/netid.conf" | fmt -u)
fi

# 安裝命令 (fping, tree, expect)
. ./lib/inscmd.sh

echo ""
for s in $nid
do
    echo "Collect Host Info : $s "
    echo "-----------------------------------------"
    fping -c 1 -g -q $s &> "/tmp/${s%/*}.chk"
    nip=$(grep "min/avg/max" "/tmp/${s%/*}.chk" | cut -d' ' -f1 | fmt -u)

    for ip in $nip
    do
       nc -w 2 $ip 22 &>/dev/null
       if [ "$?" == "0" ]; then
          $HOME/oc99.98/lib/autossh.sh $ip student student 'cat /etc/network/interfaces' &> /tmp/netchk.txt

          echo -e "<h1>$ip</h1>\n<b>IP Configuration</b>\n<pre>" > ./html/$ip.html

          grep "Permission denied" /tmp/netchk.txt &>/dev/null
          if [ "$?" != "0" ];then
             cat /tmp/netchk.txt | sed -n '/cat \/etc/,/exit/p' | grep -v 'student@' >> ./html/$ip.html
          fi
          echo -e "\n</pre>" >> ./html/$ip.html

          echo "$ip ($ip.html)"
       fi
    done
    echo ""
done

exit 0
}}}

''執行結果''
{{{
$ ./getnid.sh

Collect Host Info : 172.30.100.0/24
-----------------------------------------
172.30.100.1 (172.30.100.1.html)
172.30.100.2 (172.30.100.2.html)
172.30.100.5 (172.30.100.5.html)
172.30.100.10 (172.30.100.10.html)
172.30.100.254 (172.30.100.254.html)

Collect Host Info : 172.30.66.0/24
-----------------------------------------
172.30.66.5 (172.30.66.5.html)
172.30.66.254 (172.30.66.254.html)
}}}
<<toBalaNotes "1">>

{{item1{檢視收集結果}}}

只收集有提供 ssh 服務主機的網路資訊
{{{
$ ls html
140.137.214.104.html  140.137.214.57.html  172.30.100.5.html
140.137.214.150.html  140.137.214.66.html  172.30.100.6.html
140.137.214.161.html  172.30.100.10.html   172.30.66.254.html
140.137.214.252.html  172.30.100.1.html    172.30.66.5.html
140.137.214.253.html  172.30.100.254.html  172.30.99.254.html
140.137.214.30.html   172.30.100.2.html    172.30.99.5.html

$ cat html/172.30.100.5.html
<h1>172.30.100.5</h1>
<b>IP Configuration</b>
<pre>
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet static
  address 172.30.100.5
  netmask 255.255.255.0
  gateway 172.30.100.254

auto eth1
iface eth1 inet static
  address 172.30.66.254
  netmask 255.255.255.0

</pre>
}}}
<<toBalaNotes "2">>


///%1
//%/

///%2
//%/
[[attachlicense – script to add license into the source files|http://mohan43u.wordpress.com/2009/04/06/attachlicense-script-to-add-license-into-the-source-files/]]

Its has been some kind of twisted weekend to me, Not enough time to post, But I got some time with my lappy to create a script which will automatically add my license text,  Yes, its like the previous post, but this one is a bash script, instead of vi script(Ooh, its a damn interesting to do vi scripting.. defenately I’ll try something new with it).

Here is the script, [[attachlicense|http://go2.wordpress.com/?id=725X1342&site=mohan43u.wordpress.com&url=http%3A%2F%2Fwww.4shared.com%2Ffile%2F96997369%2Fb76d061f%2Fattachlicense.html&sref=http%3A%2F%2Fmohan43u.wordpress.com%2F2009%2F04%2F06%2Fattachlicense-script-to-add-license-into-the-source-files%2F]]
{{{
#!/bin/sh
#
# attachlicense - script to add/remove license in given source file.
# Copyright (C) 2009  "Mohan Raman" <mohan43u@gmail.com>
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# 

USAGE="[USAGE]
	attachlicense -f licensefile [-w] [-r] [-d description] 
		[-y year] [-n name] [-e email] [-v] [file ...]
"

HELP="${USAGE}

[DESCRIPTION]

	-f 	Specify license filename as 'licensefile'.
	-w	Write license to the file.
	-r 	Remove license from the file.
	-d	Description about the source file to add in license.
	-y	Year to put in license.
	-n	Name to be appeared in license.
	-e 	Email to be appeared in license.
	-v	Verbose output.
	file	Source file.

[EXAMPLES]

	$ attachlicense -f gplv2.txt -w sampleprogram.c

	will attach contents of gplv2.txt into sampleprogram.c at top of
	of the file.
"

# Defining variables and their default values

RESOLVEDFILENAME="/tmp/attachlicense.$$"
COMBINEDFILENAME="/tmp/attachlicense.$$$$"
FINALDESCRIPTION=""
NAME="${USER}"
HOSTNAME=`hostname`
YEAR=`date +"%Y"`
EMAIL="${USER}@${HOSTNAME}"
HAVELICENSE="0"
WRITEMODE="0"
REMOVEMODE="0"
VERBOSEMODE="0"

# Parsing Options

while getopts 'f:wrvhd:y:n:e:' OPTION
do
	case "${OPTION}"
	in
		f) LICENSEFILENAME="${OPTARG}";;
		w) WRITEMODE="1";;
		d) DESCRIPTION="${OPTARG}";;
		y) YEAR="${OPTARG}";;
		n) NAME="${OPTARG}";;
		e) EMAIL="${OPTARG}";;
		r) REMOVEMODE="1";;
		v) VERBOSEMODE="1";;
		h) echo "${HELP}" && exit 0;;
		\?) echo "${USAGE}" && echo "See 'attachlicense -h'" && \
			exit 1;;
		*) echo "${USAGE}" && echo "See 'attachlicense -h" && \
			exit 1;;
	esac
done

# If licensefile not given, say about that and exit.

shift $((OPTIND - 1))
test -z "${LICENSEFILENAME}" && \
	echo "Specify licensefile using -f option..." && \
	echo "See 'attachlicense -h'" && \
	exit 1

# Takeing filenames from ${@} variable

for FILENAME
do
	# If user not given discription, put filename as description

	FULLDESCRIPTION="${DESCRIPTION}"
	test -z "${FULLDESCRIPTION}" && \
		FULLDESCRIPTION=`basename "${FILENAME}"`

	# Change <description,<year>,<name>,<email> tags in license
	# file to their respective values

	sed -n 	-e"1,\$s%<description>%${FULLDESCRIPTION}%g" \
		-e"1,\$s%<year>%${YEAR}%g" \
		-e"1,\$s%<name>%\"${NAME}\"%g" \
		-e"1,\$s%<email>%<${EMAIL}>%g" \
		-e"1,\$p" \
		"${LICENSEFILENAME}" \
		> "${RESOLVEDFILENAME}"

	# If the file already contains 'Copyright' keyword, then 
	# set HAVELICENSE="1". This will decide the rest of the
	# tasks in this script.

	grep "Copyright" "${FILENAME}" 2>/dev/null 1>/dev/null && \
		HAVELICENSE="1"

	# If file don't contain license and user not requested for
	# removal, then attach license, if write mode is also present
	# then modify the original file, otherwise, just display the
	# file with attached license.

	if test "${HAVELICENSE}" = "0" && test "${REMOVEMODE}" = "0"
	then
		if test "${WRITEMODE}" = "1"
		then
			cat "${RESOLVEDFILENAME}" "${FILENAME}" \
				2>/dev/null 1>"${COMBINEDFILENAME}"

			rm -f "${FILENAME}"
	
			cp "${COMBINEDFILENAME}" "${FILENAME}" && \
			test "${VERBOSEMODE}" = "1" && \
			echo "${LICENSEFILENAME} added to ${FILENAME}"
		fi

		if test "${WRITEMODE}" = "0"
		then
			cat "${RESOLVEDFILENAME}" "${FILENAME}" \
				2>/dev/null
		fi
	fi

	# If the file contains license, and user requested for removal,
	# then delete license lines from file. If write mode is also present
	# then save the changes in original source file. otherwise, just
	# display the file with deleted contents.

	if test "${HAVELICENSE}" = "1" && test "${REMOVEMODE}" = "1"
	then
		STARTLINE="1"
		ENDLINE=`wc -l "${LICENSEFILENAME}" | tr -s ' ' | \
			cut -d' ' -f1`

		sed -n 	-e"${STARTLINE},${ENDLINE}d" \
			-e"1,\$p" \
			"${FILENAME}" \
			> "${COMBINEDFILENAME}"

		if test "${WRITEMODE}" = "1"
		then
			rm "${FILENAME}" && \
			cp "${COMBINEDFILENAME}" "${FILENAME}" && \
			test "${VERBOSEMODE}" = "1" && \
			echo "${LICENSEFILENAME}" removed from "${FILENAME}"
		fi

		if test "${WRITEMODE}" = "0"
		then
			cat "${COMBINEDFILENAME}"
		fi
	fi
done

# Remove temperory files

rm -f "${RESOLVEDFILENAME}" "${COMBINEDFILENAME}"
}}}

''And here is my customized GPLv2,''
{{{
#
# <description>
# Copyright (C) <year>  <name> <email>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see .
}}}
This script will not attach if it see a keyword already present in the source file, so forgive me to put this stupidity in place, I just wrote it for no purpose, I need to update this script to do more, but don’t have enough time to do it. To attach the license to a list of .c and .h files, all you need to do is,
{{{
$ find "${MYDEVDIR}" -name '*.sh' | xargs attachlicense -f gplv2.txt -n 'Mohan Raman' -e 'mohan43u@gmail.com' -w -v
}}}
I just showed only two options, there is more options to customize,

Finally, its just for fun script, and not yet fully completed, so please don’t try this with production sources, also if you have suggessions, let me know.

<<toBalaNotes "gpl2">>


///%gpl2
//%/

{{item1{撰寫派送管理系統程式}}}

''$ nano setnid.sh''
{{{
#!/bin/bash

[ "$USER" != "root" ] && echo "need root" && exit 1

if [ "$#" -gt 0 ]; then
   nid="$@"
else
   nid=$(cat "$HOME/oc99.98/conf/netid.conf" | fmt -u)
fi

# 安裝 fping, tree, expect 命令
. ./lib/inscmd.sh

echo ""
for s in $nid
do
    echo "$s "
    echo "--------------------------"
    fping -c 1 -g -q $s &> "/tmp/${s%/*}.chk"
    nip=$(grep "min/avg/max" "/tmp/${s%/*}.chk" | cut -d' ' -f1 | fmt -u)

    for ip in $nip
    do
       nc -w 2 $ip 22 &>/dev/null
       if [ "$?" == "0" ]; then
          $HOME/oc99.98/lib/autoscp.sh $ip student student $HOME/oc99.98/bin /home/student &>/tmp/$ip.scp
          grep "Permission denied" /tmp/$ip.scp &>/dev/null
          [ "$?" != "0" ] && echo "$ip ok"
       fi
    done
    echo ""
done

exit 0
}}}

@@color:red;''[注意]''@@ 如執行 scp 命令, 出現 "Read-only file system" 這錯誤訊息, 代表檔案無法 ''複製'' 或 ''覆蓋'', 原因是 "目地主機" 的檔案系統, 被設成 read-only, 實際例子 : 在 Linux KVM 系統, 執行 Restore Saved Machine 後, 虛擬主機的檔案系統被設成 Read Only

<<toBalaNotes "1">>


///%1
//%/
本文網址 : http://www.frostyplace.com/index.php?story_id=8761

時至今日,硬碟可說是越來越便宜,但面對琳琅滿目的品牌與款式,以及各家看似大同小異但又似乎充滿玄機的規格與功能,又讓人眼花撩亂,不知所措。到底哪一款才是最快的機種?最划算的機種?還是兩者之間能夠取個完美的平衡?根據 HotHardware 取來 Samsung 、 Seagate 與 Western Digital 三大品牌九種 3.5 吋 2TB SATA 硬碟來進行多達 250 種各式測試(可惜 Hitachi 拒絕參加), WD 有 RE4 2TB 、 Caviar Black 2TB 、 RE4-GP 2TB 、 Caviar Green 2TB 、 AV-GP 2TB 、 Caviar Black 1TB (此機非 2TB 機種)等六款, Seagate 有 Barracuda XT 2TB 、 Constellation ES 2TB 、 Barracuda LP 2TB 等三款,與 Samsung 的 EcoGreen F3 2TB 一款。

在這個多達 11 頁網頁的「Definitive 2TB HD Roundup: WD, Seagate, Samsung」報告中,最後以硬體性能、購置成本,與成本效益比三個部份來分別將這些硬碟分別排行。

在硬體性能來說,以 WD RE4 2TB 得分 112.38 最佳,其次是 WD Caviar Black 2TB 、 Seagate Barracuda XT 2TB 、 Seagate Constellation ES 2TB 與 WD Caviar Black 1TB ,得分均在 107 至 109 左右。再來的第三區間則是得分在 91 至 95 之間的 Seagate Barracuda LP 2TB 、 WD RE4-GP 2TB 與 Samsung EcoGreen F3 2TB 。而 WD Caviar Green 2TB 與 WD AV-GP 2TB 則得分為 83 上下墊底。

拔得頭籌的 WD RE4 2TB 也是最貴的機種,不過也因為如此所以通常被歸類在速度最快的企業級硬碟;而 WD Caviar Black 2TB 則是速度最快的效能級硬碟。第三區間表現最佳者 Seagate Barracuda LP 2TB 則可說是一般用途等級之王。

[img[img/10HDDCompetition1.png]]

比完性能,接下來比價格。測試人員取得 2010 年四月份的市價來除以容量,算出每 GB 的成本。結果很有趣的是這十台硬碟分成五個等級,每個等級各有兩台,分別是最便宜的 WD Caviar Green 2TB 與 Seagate Barracuda LP 2TB ,每 GB 成本為 0.07 元;第二區間是 WD AV-GP 2TB 與 Samsung EcoGreen F3 2TB 的 0.08 元;第三區間是 WD Caviar Black 1TB 與 Seagate Barracuda XT 2TB 的 0.12 元;第四則是 WD RE4-GP 2TB 與 WD Caviar Black 2TB 的 0.14 元;最貴的則是 WD RE4 2TB 與 Seagate Constellation ES 2TB 的 0.16 元。

第一與第二兩個區間的成本分別是 0.07 與 0.08 元,兩者相差不大;但再來的三個區間 0.12 、 0.14 與 0.16 相比之下就貴上一截。最貴與最便宜之間相差已經超過一倍。

[img[img/10HDDCompetition2.png]]

不過單看速度與光比成本,又失之偏頗,此時應該來就這兩者進行分析比較,也就是比比成本與效能。不過這也是建立在整體平均值的計算上,意思示若有強力的需求,就不見得要參考這個比較結果,例如企業級硬碟應該要將可靠性視為十分重要的一個考量因素,而不是光考慮速度與成本。

在成本效能比的排行榜中, WD Caviar Black 1TB 以 8.25 遙遙領先群雄;其次是得分在 5.x 區間的 Seagate Barrcuda LP 2TB 的 6.34 和 WD Caviar Green 2TB 的 5.55 ,以及 Samsung EcoGreen F3 2TB 的 5.46 。再來,是得分 4.x 區間的兩個,分別是 WD AV-GP 2TB 的 4.89 ,與 Seagate Barracuda XT 2TB 的 4.35 。最後都是得分 3.x 區間的 WD Caviar Black 2TB 、 WD RE4 2TB 、 Seagate Constellation ES 2TB 與 WD RE4-GP 2TB 。

[img[img/10HDDCompetition3.png]]

最後的成績是除了 WD AV-GP 2TB 與 RE4-GP 2TB 外,其餘都是推薦機種;其中,由於較低價格與較低耗能之故, Seagate Barracuda XT 2TB 比起 WD Caviar Black 2TB 要來得優秀;而 WD RE4 2TB 更是最後的編輯首選。
本文網址 : http://www.ithome.com.tw/itadm/article.php?c=78367

財政部財政資訊中心加上臺灣5地區的國稅局導入OpenOffice辦公軟體,目前共計8千多名員工使用,更預計在今年大幅移除原有的微軟Office軟體,只會保留5%的Office軟體授權,用於轉換對外交換的文件檔案。

在2011年時,財政資訊中心和5地區國稅局(含臺北國稅局、高雄國稅局、臺灣省北區國稅局、臺灣省中區國稅局和臺灣省南區國稅局)接下了一個政府招案,這些單位將會有密切的合作,自然文件檔案交換頻率也會增加,同時,又面臨機關內部Office軟體版本過舊,大都是微軟舊版的Office 2000或Office 2003,正好是辦公軟體的升級時機。

但是考慮到全部換新的Office軟體授權費用並不便宜,Office 2007以上版本的使用介面也和過去大不相同,財政資訊中心就開始考慮,既然使用者都要適應新介面,那不如趁這個機會導入開放格式的辦公軟體。

因為財政部屬公家機關,大部分屬敏感資料,所以辦公軟體在線上操作較有洩漏資料的疑慮,在這個考量之下,像Google雲端作業軟體自然就不在考慮範圍內。

負責導入這次專案的財政部財政資訊中心助理設計師曾政龍表示,當時財政資訊中心想買斷授權,又希望不被軟體格式限制,因此同時評估了3個自由軟體方案,分別是LibreOffice、OpenOffice和EIOffice。

但實際比較過後,發現EIOffice不夠自由,輸出的文件檔並不是ODF的開放格式,而LibreOffice對使用者使用問題的支援較不足,有問題時沒辦法立即解決。最後,財政資訊中心才選擇OpenOffice作為替換微軟Office的選擇方案。

高層主管出席教育訓練帶頭導入
決定好軟體後,財政資訊中心從2011年11月起,就開始進行OpenOffice的一連串導入措施。

首先是舉辦財政資訊中心以及5區國稅局的OpenOffice內部說明會,但重要的是,每次有內部說明會,財政資訊中心主任蘇俊榮,以及各國稅局的高層主管都會親自出席,來支持這個專案導入。

此外,蘇俊榮更會在很多公開場合宣導Open Office的好處。在推廣期間,財政資訊中心和5區國稅局甚至共同舉辦了「OpenOffice.org學習成果文件競賽」,透過競賽讓使用者熟悉這套軟體。

曾政龍表示,這次的專案能夠導入成功,有很大原因來自於高階主管的支持與親身力行,帶領底下員工嘗試和過去不同的辦公作業軟體環境。 

Canonical 認為,Ubuntu 已進化成可用來執行關鍵任務(mission critical)的伺服器平台。

Ubuntu Linux 商業贊助商 Canonical 及分析機構 RedMonk 在近日發表一份針對 Ubuntu 伺服器作業系統的使用調查報告,顯示Ubuntu Linux 已成重要的伺服器平台。

Canonical 是在去年 9月啟動這項調查,有近7千名Ubuntu伺服器作業系統的使用者回應該問卷,Canonical 的目的在於了解使用者如何利用 Ubuntu 伺服器作業系統及企業類別。

該份報告顯示,使用者主要利用 Ubuntu 執行諸如網站、資料庫、檔案、列印及郵件伺服器等一般任務,同時也有使用者利用Ubuntu 作為安全、備份及防火牆等重要平台。

根據該調查,這些Ubuntu用戶的企業使用最多的伺服器作業系統仍為Windows版本,Linux版本居次,而UNIX則排名第三;在Linux版本中,使用Ubuntu的比例最高,其他依序是紅帽的Enterprise、Debian、Centos、SuSE Linux Enterprise及Fedora等。接受調查的用戶企業大部份座落於歐洲及北美,以科技服務業佔多數,其次是軟體業及教育機構。

至於Ubuntu伺服器版本的用途排名第一的為網路伺服器或網路應用程式伺服器,其他較常見的用途還包括檔案伺服器、資料庫伺服器、電子郵件伺服器、備份伺服器、DNS伺服器、開發或測試伺服器、安全伺服器及虛擬化伺服器等。

Canonical 認為,Ubuntu已進化成可用來執行關鍵任務(mission critical)的伺服器平台,調查顯示受訪者所認為的前幾大關鍵任務包括網路伺服器、資料庫伺服器、備份伺服器、電子郵件伺服器、檔案伺服器、DNS 伺服器、安全伺服器、虛擬化伺服器等皆已是 Ubuntu 平台上的常見任務。

此外,有約9成的受訪者認為Ubuntu已可用來部署重要的企業任務。在詢問用戶所認定的重要Linux伺服器功能時,大多數受訪者認為備份功能是最重要的,其他還包括防火牆、安全、儲存及系統管理。

Canonical 亦詢問受訪者對雲端運算的看法,有超過一半的受訪者認為雲端環境已可用來執行關鍵任務,另外有超過8成的受訪者認為 Ubuntu 可作為雲端運算基礎開發平台,但問及是否有計畫在雲端環境中執行任務時,則僅有不到4成的受訪者表示有計畫。

該調查除了顯示受訪者在中、短期內有強烈的意願於資料中心中新增 Ubuntu 伺服器外,並指出最受歡迎的 Ubuntu 平台為 Ubuntu 8.04長期支援版(Long Term Support,LTS)。Ubuntu 一般的技術支援期限為18個月,但長期支援版則提供桌上型版本3年及伺服器版本5年的安全更新技術支援。

Ubuntu 以每6個月就更新一次的快速更新周期以及人性化的操作介面吸引不少 Linux 愛好者,Ubuntu 所開發的版本涵蓋桌面、伺服器及行動裝置,目前最新版本為 8.10版。
Background: #fff
Foreground: #000
PrimaryPale: #fc8
PrimaryLight: #f81
PrimaryMid: #b40
PrimaryDark: #410
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/***
|''Name:''|CryptoFunctionsPlugin|
|''Description:''|Support for cryptographic functions|
***/
//{{{
if(!version.extensions.CryptoFunctionsPlugin) {
version.extensions.CryptoFunctionsPlugin = {installed:true};

//--
//-- Crypto functions and associated conversion routines
//--

// Crypto "namespace"
function Crypto() {}

// Convert a string to an array of big-endian 32-bit words
Crypto.strToBe32s = function(str)
{
	var be = Array();
	var len = Math.floor(str.length/4);
	var i, j;
	for(i=0, j=0; i<len; i++, j+=4) {
		be[i] = ((str.charCodeAt(j)&0xff) << 24)|((str.charCodeAt(j+1)&0xff) << 16)|((str.charCodeAt(j+2)&0xff) << 8)|(str.charCodeAt(j+3)&0xff);
	}
	while (j<str.length) {
		be[j>>2] |= (str.charCodeAt(j)&0xff)<<(24-(j*8)%32);
		j++;
	}
	return be;
};

// Convert an array of big-endian 32-bit words to a string
Crypto.be32sToStr = function(be)
{
	var str = "";
	for(var i=0;i<be.length*32;i+=8)
		str += String.fromCharCode((be[i>>5]>>>(24-i%32)) & 0xff);
	return str;
};

// Convert an array of big-endian 32-bit words to a hex string
Crypto.be32sToHex = function(be)
{
	var hex = "0123456789ABCDEF";
	var str = "";
	for(var i=0;i<be.length*4;i++)
		str += hex.charAt((be[i>>2]>>((3-i%4)*8+4))&0xF) + hex.charAt((be[i>>2]>>((3-i%4)*8))&0xF);
	return str;
};

// Return, in hex, the SHA-1 hash of a string
Crypto.hexSha1Str = function(str)
{
	return Crypto.be32sToHex(Crypto.sha1Str(str));
};

// Return the SHA-1 hash of a string
Crypto.sha1Str = function(str)
{
	return Crypto.sha1(Crypto.strToBe32s(str),str.length);
};

// Calculate the SHA-1 hash of an array of blen bytes of big-endian 32-bit words
Crypto.sha1 = function(x,blen)
{
	// Add 32-bit integers, wrapping at 32 bits
	add32 = function(a,b)
	{
		var lsw = (a&0xFFFF)+(b&0xFFFF);
		var msw = (a>>16)+(b>>16)+(lsw>>16);
		return (msw<<16)|(lsw&0xFFFF);
	};
	// Add five 32-bit integers, wrapping at 32 bits
	add32x5 = function(a,b,c,d,e)
	{
		var lsw = (a&0xFFFF)+(b&0xFFFF)+(c&0xFFFF)+(d&0xFFFF)+(e&0xFFFF);
		var msw = (a>>16)+(b>>16)+(c>>16)+(d>>16)+(e>>16)+(lsw>>16);
		return (msw<<16)|(lsw&0xFFFF);
	};
	// Bitwise rotate left a 32-bit integer by 1 bit
	rol32 = function(n)
	{
		return (n>>>31)|(n<<1);
	};

	var len = blen*8;
	// Append padding so length in bits is 448 mod 512
	x[len>>5] |= 0x80 << (24-len%32);
	// Append length
	x[((len+64>>9)<<4)+15] = len;
	var w = Array(80);

	var k1 = 0x5A827999;
	var k2 = 0x6ED9EBA1;
	var k3 = 0x8F1BBCDC;
	var k4 = 0xCA62C1D6;

	var h0 = 0x67452301;
	var h1 = 0xEFCDAB89;
	var h2 = 0x98BADCFE;
	var h3 = 0x10325476;
	var h4 = 0xC3D2E1F0;

	for(var i=0;i<x.length;i+=16) {
		var j,t;
		var a = h0;
		var b = h1;
		var c = h2;
		var d = h3;
		var e = h4;
		for(j = 0;j<16;j++) {
			w[j] = x[i+j];
			t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=16;j<20;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=20;j<40;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k2);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=40;j<60;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),(b&c)|(d&(b|c)),w[j],k3);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=60;j<80;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k4);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}

		h0 = add32(h0,a);
		h1 = add32(h1,b);
		h2 = add32(h2,c);
		h3 = add32(h3,d);
		h4 = add32(h4,e);
	}
	return Array(h0,h1,h2,h3,h4);
};


}
//}}}
首頁
/***
|''Name:''|DeprecatedFunctionsPlugin|
|''Description:''|Support for deprecated functions removed from core|
***/
//{{{
if(!version.extensions.DeprecatedFunctionsPlugin) {
version.extensions.DeprecatedFunctionsPlugin = {installed:true};

//--
//-- Deprecated code
//--

// @Deprecated: Use createElementAndWikify and this.termRegExp instead
config.formatterHelpers.charFormatHelper = function(w)
{
	w.subWikify(createTiddlyElement(w.output,this.element),this.terminator);
};

// @Deprecated: Use enclosedTextHelper and this.lookaheadRegExp instead
config.formatterHelpers.monospacedByLineHelper = function(w)
{
	var lookaheadRegExp = new RegExp(this.lookahead,"mg");
	lookaheadRegExp.lastIndex = w.matchStart;
	var lookaheadMatch = lookaheadRegExp.exec(w.source);
	if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
		var text = lookaheadMatch[1];
		if(config.browser.isIE)
			text = text.replace(/\n/g,"\r");
		createTiddlyElement(w.output,"pre",null,null,text);
		w.nextMatch = lookaheadRegExp.lastIndex;
	}
};

// @Deprecated: Use <br> or <br /> instead of <<br>>
config.macros.br = {};
config.macros.br.handler = function(place)
{
	createTiddlyElement(place,"br");
};

// Find an entry in an array. Returns the array index or null
// @Deprecated: Use indexOf instead
Array.prototype.find = function(item)
{
	var i = this.indexOf(item);
	return i == -1 ? null : i;
};

// Load a tiddler from an HTML DIV. The caller should make sure to later call Tiddler.changed()
// @Deprecated: Use store.getLoader().internalizeTiddler instead
Tiddler.prototype.loadFromDiv = function(divRef,title)
{
	return store.getLoader().internalizeTiddler(store,this,title,divRef);
};

// Format the text for storage in an HTML DIV
// @Deprecated Use store.getSaver().externalizeTiddler instead.
Tiddler.prototype.saveToDiv = function()
{
	return store.getSaver().externalizeTiddler(store,this);
};

// @Deprecated: Use store.allTiddlersAsHtml() instead
function allTiddlersAsHtml()
{
	return store.allTiddlersAsHtml();
}

// @Deprecated: Use refreshPageTemplate instead
function applyPageTemplate(title)
{
	refreshPageTemplate(title);
}

// @Deprecated: Use story.displayTiddlers instead
function displayTiddlers(srcElement,titles,template,unused1,unused2,animate,unused3)
{
	story.displayTiddlers(srcElement,titles,template,animate);
}

// @Deprecated: Use story.displayTiddler instead
function displayTiddler(srcElement,title,template,unused1,unused2,animate,unused3)
{
	story.displayTiddler(srcElement,title,template,animate);
}

// @Deprecated: Use functions on right hand side directly instead
var createTiddlerPopup = Popup.create;
var scrollToTiddlerPopup = Popup.show;
var hideTiddlerPopup = Popup.remove;

// @Deprecated: Use right hand side directly instead
var regexpBackSlashEn = new RegExp("\\\\n","mg");
var regexpBackSlash = new RegExp("\\\\","mg");
var regexpBackSlashEss = new RegExp("\\\\s","mg");
var regexpNewLine = new RegExp("\n","mg");
var regexpCarriageReturn = new RegExp("\r","mg");

}
//}}}
/***
|Name|DisableWikiLinksPlugin|
|Source|http://www.TiddlyTools.com/#DisableWikiLinksPlugin|
|Version|1.5.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Tiddler.prototype.autoLinkWikiWords, 'wikiLink' formatter|
|Options|##Configuration|
|Description|selectively disable TiddlyWiki's automatic ~WikiWord linking behavior|
This plugin allows you to disable TiddlyWiki's automatic ~WikiWord linking behavior, so that WikiWords embedded in tiddler content will be rendered as regular text, instead of being automatically converted to tiddler links.  To create a tiddler link when automatic linking is disabled, you must enclose the link text within {{{[[...]]}}}.
!!!!!Usage
<<<
You can block automatic WikiWord linking behavior for any specific tiddler by ''tagging it with<<tag excludeWikiWords>>'' (see configuration below) or, check a plugin option to disable automatic WikiWord links to non-existing tiddler titles, while still linking WikiWords that correspond to existing tiddlers titles or shadow tiddler titles.  You can also block specific selected WikiWords from being automatically linked by listing them in [[DisableWikiLinksList]] (see configuration below), separated by whitespace.  This tiddler is optional and, when present, causes the listed words to always be excluded, even if automatic linking of other WikiWords is being permitted.  

Note: WikiWords contained in default ''shadow'' tiddlers will be automatically linked unless you select an additional checkbox option lets you disable these automatic links as well, though this is not recommended, since it can make it more difficult to access some TiddlyWiki standard default content (such as AdvancedOptions or SideBarTabs)
<<<
!!!!!Configuration
<<<
<<option chkDisableWikiLinks>> Disable ALL automatic WikiWord tiddler links
<<option chkAllowLinksFromShadowTiddlers>> ... except for WikiWords //contained in// shadow tiddlers
<<option chkDisableNonExistingWikiLinks>> Disable automatic WikiWord links for non-existing tiddlers
Disable automatic WikiWord links for words listed in: <<option txtDisableWikiLinksList>>
Disable automatic WikiWord links for tiddlers tagged with: <<option txtDisableWikiLinksTag>>
<<<
!!!!!Code
***/
//{{{
version.extensions.disableWikiLinks= {major: 1, minor: 5, revision: 0, date: new Date(2007,6,9)};

if (config.options.chkDisableNonExistingWikiLinks==undefined) config.options.chkDisableNonExistingWikiLinks= false;
if (config.options.chkDisableWikiLinks==undefined) config.options.chkDisableWikiLinks=false;
if (config.options.txtDisableWikiLinksList==undefined) config.options.txtDisableWikiLinksList="DisableWikiLinksList";
if (config.options.chkAllowLinksFromShadowTiddlers==undefined) config.options.chkAllowLinksFromShadowTiddlers=true;
if (config.options.txtDisableWikiLinksTag==undefined) config.options.txtDisableWikiLinksTag="excludeWikiWords";

// find the formatter for wikiLink and replace handler with 'pass-thru' rendering
initDisableWikiLinksFormatter();
function initDisableWikiLinksFormatter() {
	for (var i=0; i<config.formatters.length && config.formatters[i].name!="wikiLink"; i++);
	config.formatters[i].coreHandler=config.formatters[i].handler;
	config.formatters[i].handler=function(w) {
		// supress any leading "~" (if present)
		var skip=(w.matchText.substr(0,1)==config.textPrimitives.unWikiLink)?1:0;
		var title=w.matchText.substr(skip);
		var exists=store.tiddlerExists(title);
		var inShadow=w.tiddler && store.isShadowTiddler(w.tiddler.title);

		// check for excluded Tiddler
		if (w.tiddler && w.tiddler.isTagged(config.options.txtDisableWikiLinksTag))
			{ w.outputText(w.output,w.matchStart+skip,w.nextMatch); return; }
		
		// check for specific excluded wiki words
		var t=store.getTiddlerText(config.options.txtDisableWikiLinksList)
		if (t && t.length && t.indexOf(w.matchText)!=-1)
			{ w.outputText(w.output,w.matchStart+skip,w.nextMatch); return; }

		// if not disabling links from shadows (default setting)
		if (config.options.chkAllowLinksFromShadowTiddlers && inShadow)
			return this.coreHandler(w);

		// check for non-existing non-shadow tiddler
		if (config.options.chkDisableNonExistingWikiLinks && !exists)
			{ w.outputText(w.output,w.matchStart+skip,w.nextMatch); return; }

		// if not enabled, just do standard WikiWord link formatting
		if (!config.options.chkDisableWikiLinks)
			return this.coreHandler(w);

		// just return text without linking
		w.outputText(w.output,w.matchStart+skip,w.nextMatch)
	}
}

Tiddler.prototype.coreAutoLinkWikiWords = Tiddler.prototype.autoLinkWikiWords;
Tiddler.prototype.autoLinkWikiWords = function()
{
	// DEBUG alert("processing: "+this.title);
	// if all automatic links are not disabled, just return results from core function
	if (!config.options.chkDisableWikiLinks)
		return this.coreAutoLinkWikiWords.apply(this,arguments);
	return false;
}
//}}}
/*{{{*/
 
/*}}}*/
/*{{{*/
a {color:#0044BB;font-weight:bold}
/*}}}*/
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='easyEdit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<!--}}}-->
/***
|Name|ExportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ExportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ExportTiddlersPluginInfo|
|Version|2.7.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|select and extract tiddlers from your ~TiddlyWiki documents and save them to a separate file|
ExportTiddlersPlugin lets you select and extract tiddlers from your ~TiddlyWiki documents using interactive control panel lets you specify a destination, and then select which tiddlers to export. Tiddler data can be output as complete, stand-alone TiddlyWiki documents, or just the selected tiddlers ("~PureStore" format -- smaller files!) that can be imported directly into another ~TiddlyWiki, or as an ~RSS-compatible XML file that can be published for RSS syndication.
!!!!!Documentation
>see [[ExportTiddlersPluginInfo]]
!!!!!Code
***/
//{{{
// version
version.extensions.exportTiddlers = {major: 2, minor: 7, revision: 0, date: new Date(2008,5,27)};

// default shadow definition
config.shadowTiddlers.ExportTiddlers="<<exportTiddlers inline>>";

// add 'export' backstage task (following built-in import task)
if (config.tasks) { // TW2.2 or above
	config.tasks.exportTask = {
		text:"export",
		tooltip:"Export selected tiddlers to another file",
		content:"<<exportTiddlers inline>>"
	}
	config.backstageTasks.splice(config.backstageTasks.indexOf("importTask")+1,0,"exportTask");
}

// macro handler
config.macros.exportTiddlers = {
	label: "export tiddlers",
	prompt: "Copy selected tiddlers to an export document",
	newdefault: "export.html",
	datetimefmt: "0MM/0DD/YYYY 0hh:0mm:0ss" // for "filter date/time" edit fields
};

config.macros.exportTiddlers.handler = function(place,macroName,params) {
	if (params[0]!="inline")
		{ createTiddlyButton(place,this.label,this.prompt,onClickExportMenu); return; }
	var panel=createExportPanel(place);
	panel.style.position="static";
	panel.style.display="block";
}

function createExportPanel(place) {
	var panel=document.getElementById("exportPanel");
	if (panel) { panel.parentNode.removeChild(panel); }
	setStylesheet(config.macros.exportTiddlers.css,"exportTiddlers");
	panel=createTiddlyElement(place,"span","exportPanel",null,null)
	panel.innerHTML=config.macros.exportTiddlers.html;
	exportInitFilter();
	refreshExportList(0);
	var fn=document.getElementById("exportFilename");
	if (window.location.protocol=="file:" && !fn.value.length) {
		// get new target path/filename
		var newPath=getLocalPath(window.location.href);
		var slashpos=newPath.lastIndexOf("/"); if (slashpos==-1) slashpos=newPath.lastIndexOf("\\"); 
		if (slashpos!=-1) newPath=newPath.substr(0,slashpos+1); // trim filename
		fn.value=newPath+config.macros.exportTiddlers.newdefault;
	}
	return panel;
}

function onClickExportMenu(e)
{
	if (!e) var e = window.event;
	var parent=resolveTarget(e).parentNode;
	var panel = document.getElementById("exportPanel");
	if (panel==undefined || panel.parentNode!=parent)
		panel=createExportPanel(parent);
	var isOpen = panel.style.display=="block";
	if(config.options.chkAnimate)
		anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));
	else
		panel.style.display = isOpen ? "none" : "block" ;
	if (panel.style.display!="none") { // update list and set focus when panel is made visible
		refreshExportList(0);
		var fn=document.getElementById("exportFilename"); fn.focus(); fn.select();
	}
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();
	return(false);
}
//}}}

// // IE needs explicit scoping for functions called by browser events
//{{{
window.onClickExportMenu=onClickExportMenu;
window.onClickExportButton=onClickExportButton;
window.exportShowFilterFields=exportShowFilterFields;
window.refreshExportList=refreshExportList;
//}}}

// // CSS for floating export control panel
//{{{
config.macros.exportTiddlers.css = '\
#exportPanel {\
	display: none; position:absolute; z-index:12; width:45em; right:105%; top:6em;\
	background-color: #eee; color:#000; font-size: 10pt; line-height:110%;\
	border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\
	padding: 0.5em; margin:0em; -moz-border-radius:1em;\
}\
#exportPanel a, #exportPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\
#exportPanel table { width:100%; border:0px; padding:0px; margin:0px; font-size:10pt; line-height:110%; background:transparent; }\
#exportPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\
#exportPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\
#exportPanel select { width:98%;margin:0px;font-size:10pt;line-height:110%;}\
#exportPanel input  { width:98%;padding:0px;margin:0px;font-size:10pt;line-height:110%; }\
#exportPanel textarea  { width:98%;padding:0px;margin:0px;overflow:auto;font-size:10pt; }\
#exportPanel .box { border:1px solid black; padding:3px; margin-bottom:5px; background:#f8f8f8; -moz-border-radius:5px; }\
#exportPanel .topline { border-top:2px solid black; padding-top:3px; margin-bottom:5px; }\
#exportPanel .rad { width:auto;border:0 }\
#exportPanel .chk { width:auto;border:0 }\
#exportPanel .btn { width:auto; }\
#exportPanel .btn1 { width:98%; }\
#exportPanel .btn2 { width:48%; }\
#exportPanel .btn3 { width:32%; }\
#exportPanel .btn4 { width:24%; }\
#exportPanel .btn5 { width:19%; }\
';
//}}}

// // HTML for export control panel interface
//{{{
config.macros.exportTiddlers.html = '\
<!-- target path/file  -->\
<div>\
export to path/filename:<br>\
<input type="text" id="exportFilename" size=40 style="width:93%"><input \
	type="button" id="exportBrowse" value="..." title="select or enter a local folder/file..." style="width:5%" \
	onclick="var fn=window.promptForExportFilename(this); if (fn.length) this.previousSibling.value=fn; ">\
</div>\
\
<!-- output format -->\
<div>\
output file format:\
<select id="exportFormat" size=1>\
<option value="TW">TiddlyWiki document (includes core code)</option>\
<option value="DIV">TiddlyWiki "PureStore" file (tiddler data only)</option>\
<option value="XML">XML (for RSS newsfeed)</option>\
</select>\
</div>\
\
<!-- notes -->\
<div>\
notes:<br>\
<textarea id="exportNotes" rows=3 cols=40 style="height:4em;margin-bottom:5px;" onfocus="this.select()"></textarea> \
</div>\
\
<!-- list of tiddlers -->\
<table><tr align="left"><td>\
	select:\
	<a href="JavaScript:;" id="exportSelectAll"\
		onclick="onClickExportButton(this)" title="select all tiddlers">\
		&nbsp;all&nbsp;</a>\
	<a href="JavaScript:;" id="exportSelectChanges"\
		onclick="onClickExportButton(this)" title="select tiddlers changed since last save">\
		&nbsp;changes&nbsp;</a> \
	<a href="JavaScript:;" id="exportSelectOpened"\
		onclick="onClickExportButton(this)" title="select tiddlers currently being displayed">\
		&nbsp;opened&nbsp;</a> \
	<a href="JavaScript:;" id="exportSelectRelated"\
		onclick="onClickExportButton(this)" title="select all tiddlers related (by link or transclusion) to the currently selected tiddlers">\
		&nbsp;related&nbsp;</a> \
	<a href="JavaScript:;" id="exportToggleFilter"\
		onclick="onClickExportButton(this)" title="show/hide selection filter">\
		&nbsp;filter&nbsp;</a>  \
</td><td align="right">\
	<a href="JavaScript:;" id="exportListSmaller"\
		onclick="onClickExportButton(this)" title="reduce list size">\
		&nbsp;&#150;&nbsp;</a>\
	<a href="JavaScript:;" id="exportListLarger"\
		onclick="onClickExportButton(this)" title="increase list size">\
		&nbsp;+&nbsp;</a>\
</td></tr></table>\
<select id="exportList" multiple size="20" style="margin-bottom:5px;"\
	onchange="refreshExportList(this.selectedIndex)">\
</select><br>\
</div><!--box-->\
\
<!-- selection filter -->\
<div id="exportFilterPanel" style="display:none">\
<table><tr align="left"><td>\
	selection filter\
</td><td align="right">\
	<a href="JavaScript:;" id="exportHideFilter"\
		onclick="onClickExportButton(this)" title="hide selection filter">hide</a>\
</td></tr></table>\
<div class="box">\
<input type="checkbox" class="chk" id="exportFilterStart" value="1"\
	onclick="exportShowFilterFields(this)"> starting date/time<br>\
<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">\
	<select size=1 id="exportFilterStartBy" onchange="exportShowFilterFields(this);">\
		<option value="0">today</option>\
		<option value="1">yesterday</option>\
		<option value="7">a week ago</option>\
		<option value="30">a month ago</option>\
		<option value="site">SiteDate</option>\
		<option value="file">file date</option>\
		<option value="other">other (mm/dd/yyyy hh:mm)</option>\
	</select>\
</td><td width="50%">\
	<input type="text" id="exportStartDate" onfocus="this.select()"\
		onchange="document.getElementById(\'exportFilterStartBy\').value=\'other\';">\
</td></tr></table>\
<input type="checkbox" class="chk" id="exportFilterEnd" value="1"\
	onclick="exportShowFilterFields(this)"> ending date/time<br>\
<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">\
	<select size=1 id="exportFilterEndBy" onchange="exportShowFilterFields(this);">\
		<option value="0">today</option>\
		<option value="1">yesterday</option>\
		<option value="7">a week ago</option>\
		<option value="30">a month ago</option>\
		<option value="site">SiteDate</option>\
		<option value="file">file date</option>\
		<option value="other">other (mm/dd/yyyy hh:mm)</option>\
	</select>\
</td><td width="50%">\
	<input type="text" id="exportEndDate" onfocus="this.select()"\
		onchange="document.getElementById(\'exportFilterEndBy\').value=\'other\';">\
</td></tr></table>\
<input type="checkbox" class="chk" id=exportFilterTags value="1"\
	onclick="exportShowFilterFields(this)"> match tags<br>\
<input type="text" id="exportTags" onfocus="this.select()">\
<input type="checkbox" class="chk" id=exportFilterText value="1"\
	onclick="exportShowFilterFields(this)"> match titles/tiddler text<br>\
<input type="text" id="exportText" onfocus="this.select()">\
</div> <!--box-->\
</div> <!--panel-->\
\
<!-- action buttons -->\
<div style="text-align:center">\
<input type=button class="btn4" onclick="onClickExportButton(this)"\
	id="exportFilter" value="apply filter">\
<input type=button class="btn4" onclick="onClickExportButton(this)"\
	id="exportStart" value="export tiddlers">\
<input type=button class="btn4" onclick="onClickExportButton(this)"\
	id="exportDelete" value="delete tiddlers">\
<input type=button class="btn4" onclick="onClickExportButton(this)"\
	id="exportClose" value="close">\
</div><!--center-->\
';
//}}}

// // initialize interface

// // exportInitFilter()
//{{{
function exportInitFilter() {
	// start date
	document.getElementById("exportFilterStart").checked=false;
	document.getElementById("exportStartDate").value="";
	// end date
	document.getElementById("exportFilterEnd").checked=false;
	document.getElementById("exportEndDate").value="";
	// tags
	document.getElementById("exportFilterTags").checked=false;
	document.getElementById("exportTags").value="";
	// text
	document.getElementById("exportFilterText").checked=false;
	document.getElementById("exportText").value="";
	// show/hide filter input fields
	exportShowFilterFields();
}
//}}}

// // exportShowFilterFields(which)
//{{{
function exportShowFilterFields(which) {
	var show;

	show=document.getElementById('exportFilterStart').checked;
	document.getElementById('exportFilterStartBy').style.display=show?"block":"none";
	document.getElementById('exportStartDate').style.display=show?"block":"none";
	var val=document.getElementById('exportFilterStartBy').value;
	document.getElementById('exportStartDate').value
		=getFilterDate(val,'exportStartDate').formatString(config.macros.exportTiddlers.datetimefmt);
	 if (which && (which.id=='exportFilterStartBy') && (val=='other'))
		document.getElementById('exportStartDate').focus();

	show=document.getElementById('exportFilterEnd').checked;
	document.getElementById('exportFilterEndBy').style.display=show?"block":"none";
	document.getElementById('exportEndDate').style.display=show?"block":"none";
	var val=document.getElementById('exportFilterEndBy').value;
	document.getElementById('exportEndDate').value
		=getFilterDate(val,'exportEndDate').formatString(config.macros.exportTiddlers.datetimefmt);
	 if (which && (which.id=='exportFilterEndBy') && (val=='other'))
		document.getElementById('exportEndDate').focus();

	show=document.getElementById('exportFilterTags').checked;
	document.getElementById('exportTags').style.display=show?"block":"none";

	show=document.getElementById('exportFilterText').checked;
	document.getElementById('exportText').style.display=show?"block":"none";
}
//}}}

// // onClickExportButton(which): control interactions
//{{{
function onClickExportButton(which)
{
	// DEBUG alert(which.id);
	var theList=document.getElementById('exportList'); if (!theList) return;
	var count = 0;
	var total = store.getTiddlers('title').length;
	switch (which.id)
		{
		case 'exportFilter':
			count=filterExportList();
			var panel=document.getElementById('exportFilterPanel');
			if (count==-1) { panel.style.display='block'; break; }
			document.getElementById("exportStart").disabled=(count==0);
			document.getElementById("exportDelete").disabled=(count==0);
			clearMessage(); displayMessage("filtered "+formatExportMessage(count,total));
			if (count==0) { alert("No tiddlers were selected"); panel.style.display='block'; }
			break;
		case 'exportStart':
			exportTiddlers();
			break;
		case 'exportDelete':
			exportDeleteTiddlers();
			break;
		case 'exportHideFilter':
		case 'exportToggleFilter':
			var panel=document.getElementById('exportFilterPanel')
			panel.style.display=(panel.style.display=='block')?'none':'block';
			break;
		case 'exportSelectChanges':
			var lastmod=new Date(document.lastModified);
			for (var t = 0; t < theList.options.length; t++) {
				if (theList.options[t].value=="") continue;
				var tiddler=store.getTiddler(theList.options[t].value); if (!tiddler) continue;
				theList.options[t].selected=(tiddler.modified>lastmod);
				count += (tiddler.modified>lastmod)?1:0;
			}
			document.getElementById("exportStart").disabled=(count==0);
			document.getElementById("exportDelete").disabled=(count==0);
			clearMessage(); displayMessage(formatExportMessage(count,total));
			if (count==0) alert("There are no unsaved changes");
			break;
		case 'exportSelectAll':
			for (var t = 0; t < theList.options.length; t++) {
				if (theList.options[t].value=="") continue;
				theList.options[t].selected=true;
				count += 1;
			}
			document.getElementById("exportStart").disabled=(count==0);
			document.getElementById("exportDelete").disabled=(count==0);
			clearMessage(); displayMessage(formatExportMessage(count,count));
			break;
		case 'exportSelectOpened':
			for (var t = 0; t < theList.options.length; t++) theList.options[t].selected=false;
			var tiddlerDisplay = document.getElementById("tiddlerDisplay"); // for TW2.1-
			if (!tiddlerDisplay) tiddlerDisplay = document.getElementById("storyDisplay"); // for TW2.2+
			for (var t=0;t<tiddlerDisplay.childNodes.length;t++) {
				var tiddler=tiddlerDisplay.childNodes[t].id.substr(7);
				for (var i = 0; i < theList.options.length; i++) {
					if (theList.options[i].value!=tiddler) continue;
					theList.options[i].selected=true; count++; break;
				}
			}
			document.getElementById("exportStart").disabled=(count==0);
			document.getElementById("exportDelete").disabled=(count==0);
			clearMessage(); displayMessage(formatExportMessage(count,total));
			if (count==0) alert("There are no tiddlers currently opened");
			break;
		case 'exportSelectRelated':
			// recursively build list of related tiddlers
			function getRelatedTiddlers(tid,tids) {
				var t=store.getTiddler(tid); if (!t || tids.contains(tid)) return tids;
				tids.push(t.title);
				if (!t.linksUpdated) t.changed();
				for (var i=0; i<t.links.length; i++)
					if (t.links[i]!=tid) tids=getRelatedTiddlers(t.links[i],tids);
				return tids;
			}
			// for all currently selected tiddlers, gather up the related tiddlers (including self) and select them as well
			var tids=[];
			for (var i=0; i<theList.options.length; i++)
				if (theList.options[i].selected) tids=getRelatedTiddlers(theList.options[i].value,tids);
			// select related tiddlers (includes original selected tiddlers)
			for (var i=0; i<theList.options.length; i++)
				theList.options[i].selected=tids.contains(theList.options[i].value);
			clearMessage(); displayMessage(formatExportMessage(tids.length,total));
			break;
		case 'exportListSmaller':	// decrease current listbox size
			var min=5;
			theList.size-=(theList.size>min)?1:0;
			break;
		case 'exportListLarger':	// increase current listbox size
			var max=(theList.options.length>25)?theList.options.length:25;
			theList.size+=(theList.size<max)?1:0;
			break;
		case 'exportClose':
			document.getElementById('exportPanel').style.display='none';
			break;
		}
}
//}}}

// // promptForFilename(msg,path,file) uses platform/browser specific functions to get local filespec
//{{{
window.promptForExportFilename=function(here)
{
	var msg=here.title; // use tooltip as dialog box message
	var path=getLocalPath(document.location.href);
	var slashpos=path.lastIndexOf("/"); if (slashpos==-1) slashpos=path.lastIndexOf("\\"); 
	if (slashpos!=-1) path = path.substr(0,slashpos+1); // remove filename from path, leave the trailing slash
	var file=config.macros.exportTiddlers.newdefault;
	var result="";
	if(window.Components) { // moz
		try {
			netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
			var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
			var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
			picker.init(window, msg, nsIFilePicker.modeSave);
			var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
			thispath.initWithPath(path);
			picker.displayDirectory=thispath;
			picker.defaultExtension='html';
			picker.defaultString=file;
			picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
			if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
		}
		catch(e) { alert('error during local file access: '+e.toString()) }
	}
	else { // IE
		try { // XPSP2 IE only
			var s = new ActiveXObject('UserAccounts.CommonDialog');
			s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';
			s.FilterIndex=3; // default to HTML files;
			s.InitialDir=path;
			s.FileName=file;
			if (s.showOpen()) var result=s.FileName;
		}
		catch(e) {  // fallback
			var result=prompt(msg,path+file);
		}
	}
	return result;
}
//}}}

// // list display
//{{{
function formatExportMessage(count,total)
{
	var txt=total+' tiddler'+((total!=1)?'s':'')+" - ";
	txt += (count==0)?"none":(count==total)?"all":count;
	txt += " selected for export";
	return txt;
}

function refreshExportList(selectedIndex)
{
	var theList  = document.getElementById("exportList");
	var sort;
	if (!theList) return;
	// get the sort order
	if (!selectedIndex)   selectedIndex=0;
	if (selectedIndex==0) sort='modified';
	if (selectedIndex==1) sort='title';
	if (selectedIndex==2) sort='modified';
	if (selectedIndex==3) sort='modifier';
	if (selectedIndex==4) sort='tags';

	// unselect headings and count number of tiddlers actually selected
	var count=0;
	for (var t=5; t < theList.options.length; t++) {
		if (!theList.options[t].selected) continue;
		if (theList.options[t].value!="")
			count++;
		else { // if heading is selected, deselect it, and then select and count all in section
			theList.options[t].selected=false;
			for ( t++; t<theList.options.length && theList.options[t].value!=""; t++) {
				theList.options[t].selected=true;
				count++;
			}
		}
	}

	// disable "export" and "delete" buttons if no tiddlers selected
	document.getElementById("exportStart").disabled=(count==0);
	document.getElementById("exportDelete").disabled=(count==0);
	// show selection count
	var tiddlers = store.getTiddlers('title');
	if (theList.options.length) { clearMessage(); displayMessage(formatExportMessage(count,tiddlers.length)); }

	// if a [command] item, reload list... otherwise, no further refresh needed
	if (selectedIndex>4)  return;

	// clear current list contents
	while (theList.length > 0) { theList.options[0] = null; }
	// add heading and control items to list
	var i=0;
	var indent=String.fromCharCode(160)+String.fromCharCode(160);
	theList.options[i++]=
		new Option(tiddlers.length+" tiddlers in document", "",false,false);
	theList.options[i++]=
		new Option(((sort=="title"        )?">":indent)+' [by title]', "",false,false);
	theList.options[i++]=
		new Option(((sort=="modified")?">":indent)+' [by date]', "",false,false);
	theList.options[i++]=
		new Option(((sort=="modifier")?">":indent)+' [by author]', "",false,false);
	theList.options[i++]=
		new Option(((sort=="tags"	)?">":indent)+' [by tags]', "",false,false);
	// output the tiddler list
	switch(sort)
		{
		case "title":
			for(var t = 0; t < tiddlers.length; t++)
				theList.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);
			break;
		case "modifier":
		case "modified":
			var tiddlers = store.getTiddlers(sort);
			// sort descending for newest date first
			tiddlers.sort(function (a,b) {if(a[sort] == b[sort]) return(0); else return (a[sort] > b[sort]) ? -1 : +1; });
			var lastSection = "";
			for(var t = 0; t < tiddlers.length; t++)
				{
				var tiddler = tiddlers[t];
				var theSection = "";
				if (sort=="modified") theSection=tiddler.modified.toLocaleDateString();
				if (sort=="modifier") theSection=tiddler.modifier;
				if (theSection != lastSection)
					{
					theList.options[i++] = new Option(theSection,"",false,false);
					lastSection = theSection;
					}
				theList.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);
				}
			 break;
		case "tags":
			var theTitles = {}; // all tiddler titles, hash indexed by tag value
			var theTags = new Array();
			for(var t=0; t<tiddlers.length; t++) {
				var title=tiddlers[t].title;
				var tags=tiddlers[t].tags;
				if (!tags || !tags.length) {
					if (theTitles["untagged"]==undefined) { theTags.push("untagged"); theTitles["untagged"]=new Array(); }
					theTitles["untagged"].push(title);
				}
				else for(var s=0; s<tags.length; s++) {
					if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }
					theTitles[tags[s]].push(title);
				}
			}
			theTags.sort();
			for(var tagindex=0; tagindex<theTags.length; tagindex++) {
				var theTag=theTags[tagindex];
				theList.options[i++]=new Option(theTag,"",false,false);
				for(var t=0; t<theTitles[theTag].length; t++)
					theList.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);
			}
			break;
		}
	theList.selectedIndex=selectedIndex;		  // select current control item
	document.getElementById("exportStart").disabled=true;
	document.getElementById("exportDelete").disabled=true;
	clearMessage(); displayMessage(formatExportMessage(0,tiddlers.length));
}
//}}}

// // list filtering
//{{{
function getFilterDate(val,id)
{
	var result=0;
	switch (val) {
		case 'site':
			var timestamp=store.getTiddlerText("SiteDate");
			if (!timestamp) timestamp=document.lastModified;
			result=new Date(timestamp);
			break;
		case 'file':
			result=new Date(document.lastModified);
			break;
		case 'other':
			result=new Date(document.getElementById(id).value);
			break;
		default: // today=0, yesterday=1, one week=7, two weeks=14, a month=31
			var now=new Date(); var tz=now.getTimezoneOffset()*60000; now-=tz;
			var oneday=86400000;
			if (id=='exportStartDate')
				result=new Date((Math.floor(now/oneday)-val)*oneday+tz);
			else
				result=new Date((Math.floor(now/oneday)-val+1)*oneday+tz-1);
			break;
	}
	// DEBUG alert('getFilterDate('+val+','+id+')=='+result+"\nnow="+now);
	return result;
}

function filterExportList()
{
	var theList  = document.getElementById("exportList"); if (!theList) return -1;

	var filterStart=document.getElementById("exportFilterStart").checked;
	var val=document.getElementById("exportFilterStartBy").value;
	var startDate=getFilterDate(val,'exportStartDate');

	var filterEnd=document.getElementById("exportFilterEnd").checked;
	var val=document.getElementById("exportFilterEndBy").value;
	var endDate=getFilterDate(val,'exportEndDate');

	var filterTags=document.getElementById("exportFilterTags").checked;
	var tags=document.getElementById("exportTags").value;

	var filterText=document.getElementById("exportFilterText").checked;
	var text=document.getElementById("exportText").value;

	if (!(filterStart||filterEnd||filterTags||filterText)) {
		alert("Please set the selection filter");
		document.getElementById('exportFilterPanel').style.display="block";
		return -1;
	}
	if (filterStart&&filterEnd&&(startDate>endDate)) {
		var msg="starting date/time:\n"
		msg+=startDate.toLocaleString()+"\n";
		msg+="is later than ending date/time:\n"
		msg+=endDate.toLocaleString()
		alert(msg);
		return -1;
	}

	// if filter by tags, set up conditional expression
	if (filterTags) {
		var all = store.getTags(); // get list of all tags
		for (var i=0; i<all.length; i++) all[i]=all[i][0]; // remove tag counts
		// convert "tag1 AND ( tag2 OR NOT tag3 )"
		// into javascript expression containing regexp tests:
		// "/\~tag1\~/.test(...) && ( /\~tag2\~/.test(...) || ! /\~tag2\~/.test(...) )"
		var c=tags;
		c = c.replace(/[\[\]]/g,""); // remove [[...]] quoting around tagvalues
		// change AND/OR/NOT/parens to javascript operators and delimit terms with "~"
		c = c.replace(/\sand\s/ig,"~&&~");
		c = c.replace(/\sor\s/ig,"~||~");
		c = c.replace(/(\s)?not([\s\(])/ig,"~!~$2");
		c = c.replace(/([\(\)])/ig,"~$1~");
		// change existing tags to regexp tests and non-existing tags to "false"
		var terms=c.split("~");
		for (var i=0; i<terms.length; i++) { var t=terms[i];
			if (/(&&)|(\|\|)|[!\(\)]/.test(t) || t=="") continue; // skip operators/parens/spaces
			terms[i]=!all.contains(t)?"false":("/\\~"+t+"\\~/.test(tiddlertags)");
		}
		c=terms.join(" ");
	}
	function matchTags(t,c) {
		if (!c||!c.trim().length) return false;
		// assemble tags from tiddler into string "~tag1~tag2~tag3~"
		var tiddlertags = "~"+t.tags.join("~")+"~";
		// eval string against boolean test expression
		try { if(eval(c)) return true; }
		catch(e) { displayMessage(e.toString()); }
		return false;
	}
	
	// scan list and select tiddlers that match all applicable criteria
	var total=0;
	var count=0;
	for (var i=0; i<theList.options.length; i++) {
		// get item, skip non-tiddler list items (section headings)
		var opt=theList.options[i]; if (opt.value=="") continue;
		// get tiddler, skip missing tiddlers (this should NOT happen)
		var tiddler=store.getTiddler(opt.value); if (!tiddler) continue; 
		var sel=true;
		if ( (filterStart && tiddler.modified<startDate)
		|| (filterEnd && tiddler.modified>endDate)
		|| (filterTags && !matchTags(tiddler,c))
		|| (filterText && (tiddler.text.indexOf(text)==-1) && (tiddler.title.indexOf(text)==-1)))
			sel=false;
		opt.selected=sel;
		count+=sel?1:0;
		total++;
	}
	return count;
}
//}}}

// // OUTPUT FORMATTING AND FILE I/O
//{{{
function exportTWHeader()
{
	// get the TiddlyWiki core code source
	var sourcefile=getLocalPath(document.location.href);
	var source=loadFile(sourcefile);
	if(source==null) { alert(config.messages.cantSaveError); return null; }
	// reset existing HTML source markup
	source=updateMarkupBlock(source,"PRE-HEAD");
	source=updateMarkupBlock(source,"POST-HEAD");
	source=updateMarkupBlock(source,"PRE-BODY");
	source=updateMarkupBlock(source,"POST-BODY");
	// find store area
	var posOpeningDiv=source.indexOf(startSaveArea);
	var posClosingDiv=source.lastIndexOf(endSaveArea);
	if((posOpeningDiv==-1)||(posClosingDiv==-1))
		{ alert(config.messages.invalidFileError.format([sourcefile])); return; }
	// return everything up to store area
	return source.substr(0,posOpeningDiv+startSaveArea.length);
}

function exportTWFooter()
{
	// get the TiddlyWiki core code source
	var sourcefile=getLocalPath(document.location.href);
	var source=loadFile(sourcefile);
	if(source==null) { alert(config.messages.cantSaveError); return null; }
	// reset existing HTML source markup
	source=updateMarkupBlock(source,"PRE-HEAD");
	source=updateMarkupBlock(source,"POST-HEAD");
	source=updateMarkupBlock(source,"PRE-BODY");
	source=updateMarkupBlock(source,"POST-BODY");
	// find store area
	var posOpeningDiv=source.indexOf(startSaveArea);
	var posClosingDiv=source.lastIndexOf(endSaveArea);
	if((posOpeningDiv==-1)||(posClosingDiv==-1))
		{ alert(config.messages.invalidFileError.format([sourcefile])); return; }
	// return everything after store area
	return source.substr(posClosingDiv);
}

function exportDIVHeader()
{
	var out=[];
	var now = new Date();
	var title = convertUnicodeToUTF8(wikifyPlain("SiteTitle").htmlEncode());
	var subtitle = convertUnicodeToUTF8(wikifyPlain("SiteSubtitle").htmlEncode());
	var user = convertUnicodeToUTF8(config.options.txtUserName.htmlEncode());
	var twver = version.major+"."+version.minor+"."+version.revision;
	var pver = version.extensions.exportTiddlers.major+"."
		+version.extensions.exportTiddlers.minor+"."+version.extensions.exportTiddlers.revision;
	out.push("<html><body>");
	out.push("<style type=\"text/css\">");
	out.push("#storeArea {display:block;margin:1em;}");
	out.push("#storeArea div");
	out.push("{padding:0.5em;margin:1em;border:2px solid black;height:10em;overflow:auto;}");
	out.push("#javascriptWarning");
	out.push("{width:100%;text-align:left;background-color:#eeeeee;padding:1em;}");
	out.push("</style>");
	out.push("<div id=\"javascriptWarning\">");
	out.push("TiddlyWiki export file<br>");
	out.push("Source"+": <b>"+convertUnicodeToUTF8(document.location.href)+"</b><br>");
	out.push("Title: <b>"+title+"</b><br>");
	out.push("Subtitle: <b>"+subtitle+"</b><br>");
	out.push("Created: <b>"+now.toLocaleString()+"</b> by <b>"+user+"</b><br>");
	out.push("TiddlyWiki "+twver+" / "+"ExportTiddlersPlugin "+pver+"<br>");
	out.push("Notes:<hr><pre>"+document.getElementById("exportNotes").value.replace(/\n/g,"<br>")+"</pre>");
	out.push("</div>");
	out.push("<div id=\"storeArea\">");
	return out;
}

function exportDIVFooter()
{
	return ["</div><!--POST-BODY-START-->\n<!--POST-BODY-END--></body></html>"];
}

function exportXMLHeader()
{
	var out=[];
	var now = new Date();
	var u = store.getTiddlerText("SiteUrl",null);
	var title = convertUnicodeToUTF8(wikifyPlain("SiteTitle").htmlEncode());
	var subtitle = convertUnicodeToUTF8(wikifyPlain("SiteSubtitle").htmlEncode());
	var user = convertUnicodeToUTF8(config.options.txtUserName.htmlEncode());
	var twver = version.major+"."+version.minor+"."+version.revision;
	var pver = version.extensions.exportTiddlers.major+"."
		+version.extensions.exportTiddlers.minor+"."+version.extensions.exportTiddlers.revision;
	out.push("<" + "?xml version=\"1.0\"?" + ">");
	out.push("<rss version=\"2.0\">");
	out.push("<channel>");
	out.push("<title>" + title + "</title>");
	if(u) out.push("<link>" + convertUnicodeToUTF8(u.htmlEncode()) + "</link>");
	out.push("<description>" + subtitle + "</description>");
	out.push("<language>en-us</language>");
	out.push("<copyright>Copyright " + now.getFullYear() + " " + user + "</copyright>");
	out.push("<pubDate>" + now.toGMTString() + "</pubDate>");
	out.push("<lastBuildDate>" + now.toGMTString() + "</lastBuildDate>");
	out.push("<docs>http://blogs.law.harvard.edu/tech/rss</docs>");
	out.push("<generator>TiddlyWiki "+twver+" plus ExportTiddlersPlugin "+pver+"</generator>");
	return out;
}

function exportXMLFooter()
{
	return ["</channel></rss>"];
}

function exportData(target,list,fmt)
{
	function getData(s,f,t) { var r="";
		switch (f) {
			case "TW": r=s.getSaver().externalizeTiddler(s,t); break;
			case "DIV": r=t.title+"\n"+s.getSaver().externalizeTiddler(s,t); break;
			case "XML": r=t.saveToRss(store.getTiddlerText("SiteUrl","")); break;
		}
		return convertUnicodeToUTF8(r);
	}

	var out=[]; var tids=[];
	// get selected tiddlers
	for (var i=0; i<list.options.length; i++) {
		var opt=list.options[i]; if (!opt.selected||!opt.value.length) continue;
		var tid=store.getTiddler(opt.value); if (!tid) continue;
		tids.push(tid.title);
		out.push(getData(store,fmt,tid));
	}
	var count=out.length;
	// merge with existing tiddlers
	var text=loadFile(target);
	if (text && text.length) {
		var msg=target+"\nalready contains tiddler definitions.\n";
		msg+="\nPress OK to add new/revised tiddlers to current file contents.";
		msg+="\nPress Cancel to completely replace file contents";
		var remoteStore=new TiddlyWiki();
		if (remoteStore.importTiddlyWiki(text) && confirm(msg)) {
			var existing=remoteStore.getTiddlers("title");
			for (var i=0; i<existing.length; i++)
				if (!tids.contains(existing[i].title))
					out.push(getData(remoteStore,fmt,existing[i]));
			var msg="Merged %0 new/revised tiddlers and %1 existing tiddlers";
			displayMessage(msg.format([count,out.length-count]));
		}
	}
	return out;
}
//}}}

// // exportTiddlers(): output selected data to local file
//{{{
function exportTiddlers()
{
	clearMessage();
	var list  = document.getElementById("exportList"); if (!list) return;
	var fmt = document.getElementById("exportFormat").value;
	var target = document.getElementById("exportFilename").value.trim();
	if (!target.length) {
		displayMessage("A local target path/filename is required",target);
		return;
	}
	switch (fmt) {
		case "TW":	var head=exportTWHeader(); break;
		case "DIV":	var head=exportDIVHeader(); break;
		case "XML":	var head=exportXMLHeader(); break;
	}
	var theData=exportData(target,list,fmt);
	var c=theData.length;
	switch (fmt) {
		case "TW":	var foot=exportTWFooter(); break;
		case "DIV":	var foot=exportDIVFooter(); break;
		case "XML":	var foot=exportXMLFooter(); break;
	}
	var out=[]; var txt=out.concat(head,theData,foot).join("\n");
	var msg="An error occurred while saving to "+target;
	if (saveFile(target,txt)) msg=c+" tiddler"+((c!=1)?"s":"")+" written to "+target;
	displayMessage(msg,"file:///"+target);
}
//}}}

// // exportDeleteTiddlers(): delete selected tiddlers from file
//{{{
function exportDeleteTiddlers()
{
	var list=document.getElementById("exportList"); if (!list) return;
	var tids=[];
	for (i=0;i<list.length;i++)
		if (list.options[i].selected && list.options[i].value.length)
			tids.push(list.options[i].value);
	if (!confirm("Are you sure you want to delete these tiddlers:\n\n"+tids.join(', '))) return;
	store.suspendNotifications();
	for (t=0;t<tids.length;t++) {
		var tid=store.getTiddler(tids[t]); if (!tid) continue;
		if (tid.tags.contains("systemConfig"))
			if (!confirm("'"+tid.title+"' is tagged with 'systemConfig'.\n\nRemoving this tiddler may cause unexpected results.  Are you sure?"))
				continue;
		store.removeTiddler(tid.title);
		story.closeTiddler(tid.title);
	}
	store.resumeNotifications();
	alert(tids.length+" tiddlers deleted");
	refreshExportList(0); // reload listbox
	store.notifyAll(); // update page display
}
//}}}
/***
|''Name:''|FieldsEditorPlugin|
|''Description:''|//create//, //edit//, //view// and //delete// commands in toolbar <<toolbar fields>>.|
|''Version:''|1.0.2|
|''Date:''|Dec 21,2007|
|''Source:''|http://visualtw.ouvaton.org/VisualTW.html|
|''Author:''|Pascal Collin|
|''License:''|[[BSD open source license|License]]|
|''~CoreVersion:''|2.2.0|
|''Browser:''|Firefox 2.0; InternetExplorer 6.0, others|
!Demo:
On [[homepage|http://visualtw.ouvaton.org/VisualTW.html]], see [[FieldEditor example]]
!Installation:
*import this tiddler from [[homepage|http://visualtw.ouvaton.org/VisualTW.html]] (tagged as systemConfig)
*save and reload
*optionnaly : add the following css text in your StyleSheet : {{{#popup tr.fieldTableRow td {padding:1px 3px 1px 3px;}}}}
!Code
***/

//{{{

config.commands.fields.handlePopup = function(popup,title) {
	var tiddler = store.fetchTiddler(title);
	if(!tiddler)
		return;
	var fields = {};
	store.forEachField(tiddler,function(tiddler,fieldName,value) {fields[fieldName] = value;},true);
	var items = [];
	for(var t in fields) {
		var editCommand = "<<untiddledCall editFieldDialog "+escape(title)+" "+escape(t)+">>";
		var deleteCommand = "<<untiddledCall deleteField "+escape(title)+" "+escape(t)+">>";
		var renameCommand = "<<untiddledCall renameField "+escape(title)+" "+escape(t)+">>";
		items.push({field: t,value: fields[t], actions: editCommand+renameCommand+deleteCommand});
	}
	items.sort(function(a,b) {return a.field < b.field ? -1 : (a.field == b.field ? 0 : +1);});
	var createNewCommand = "<<untiddledCall createField "+escape(title)+">>";
	items.push({field : "", value : "", actions:createNewCommand });
	if(items.length > 0)
		ListView.create(popup,items,this.listViewTemplate);
	else
		createTiddlyElement(popup,"div",null,null,this.emptyText);
}

config.commands.fields.listViewTemplate = {
	columns: [
		{name: 'Field', field: 'field', title: "Field", type: 'String'},
		{name: 'Actions', field: 'actions', title: "Actions", type: 'WikiText'},
		{name: 'Value', field: 'value', title: "Value", type: 'WikiText'}
	],
	rowClasses: [
			{className: 'fieldTableRow', field: 'actions'}
	],
	buttons: [	//can't use button for selected then delete, because click on checkbox will hide the popup
	]
}

config.macros.untiddledCall = {  // when called from listview, tiddler is unset, so we need to pass tiddler as parameter
	handler : function(place,macroName,params,wikifier,paramString) {
		var macroName = params.shift();
		if (macroName) var macro = config.macros[macroName];
		var title = params.shift();
		if (title) var tiddler = store.getTiddler(unescape(title));
		if (macro) macro.handler(place,macroName,params,wikifier,paramString,tiddler);		
	}
}

config.macros.deleteField = {
	handler : function(place,macroName,params,wikifier,paramString,tiddler) {
		if(!readOnly && params[0]) {
			fieldName = unescape(params[0]);
			var btn = createTiddlyButton(place,"delete", "delete "+fieldName,this.onClickDeleteField);
			btn.setAttribute("title",tiddler.title);
			btn.setAttribute("fieldName", fieldName);
		}
	},
	onClickDeleteField : function() {
		var title=this.getAttribute("title");
		var fieldName=this.getAttribute("fieldName");
		var tiddler = store.getTiddler(title);
		if (tiddler && fieldName && confirm("delete field " + fieldName+" from " + title +" tiddler ?")) {
			delete tiddler.fields[fieldName];
			store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
			story.refreshTiddler(title,"ViewTemplate",true);
		}
		return false;
	}
}

config.macros.createField = {
	handler : function(place,macroName,params,wikifier,paramString,tiddler) {
		if(!readOnly) {
			var btn = createTiddlyButton(place,"create new", "create a new field",this.onClickCreateField);
			btn.setAttribute("title",tiddler.title);
		}
	},
	onClickCreateField : function() {
		var title=this.getAttribute("title");
		var tiddler = store.getTiddler(title);
		if (tiddler) {
			var fieldName = prompt("Field name","");
			if (store.getValue(tiddler,fieldName)) {
				window.alert("This field already exists.");
			}
			else if (fieldName) {
				var v = prompt("Field value","");
				tiddler.fields[fieldName]=v;
				store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
				story.refreshTiddler(title,"ViewTemplate",true);
			}
		}
		return false;
	}
}

config.macros.editFieldDialog = {
	handler : function(place,macroName,params,wikifier,paramString,tiddler) {
		if(!readOnly && params[0]) {
			fieldName = unescape(params[0]);
			var btn = createTiddlyButton(place,"edit", "edit this field",this.onClickEditFieldDialog);
			btn.setAttribute("title",tiddler.title);
			btn.setAttribute("fieldName", fieldName);
		}
	},
	onClickEditFieldDialog : function() {
		var title=this.getAttribute("title");
		var tiddler = store.getTiddler(title);
		var fieldName=this.getAttribute("fieldName");
		if (tiddler && fieldName) {
			var value = tiddler.fields[fieldName];
			value = value ? value : "";
			var lines = value.match(/\n/mg);
			lines = lines ? true : false;
			if (!lines || confirm("This field contains more than one line. Only the first line will be kept if you edit it here. Proceed ?")) {
				var v = prompt("Field value",value);
				tiddler.fields[fieldName]=v;
				store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
				story.refreshTiddler(title,"ViewTemplate",true);
			}
		}
		return false;
	}
}

config.macros.renameField = {
	handler : function(place,macroName,params,wikifier,paramString,tiddler) {
		if(!readOnly && params[0]) {
			fieldName = unescape(params[0]);
			var btn = createTiddlyButton(place,"rename", "rename "+fieldName,this.onClickRenameField);
			btn.setAttribute("title",tiddler.title);
			btn.setAttribute("fieldName", fieldName);
		}
	},
	onClickRenameField : function() {
		var title=this.getAttribute("title");
		var fieldName=this.getAttribute("fieldName");
		var tiddler = store.getTiddler(title);
		if (tiddler && fieldName) {
			var newName = prompt("Rename " + fieldName + " as ?", fieldName);
			if (newName) {
				tiddler.fields[newName]=tiddler.fields[fieldName];
				delete tiddler.fields[fieldName];
				store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
				story.refreshTiddler(title,"ViewTemplate",true);
			}
		}
		return false;
	}
}

config.shadowTiddlers.StyleSheetFieldsEditor = "/*{{{*/\n";
config.shadowTiddlers.StyleSheetFieldsEditor += ".fieldTableRow td {padding : 1px 3px}\n";
config.shadowTiddlers.StyleSheetFieldsEditor += ".fieldTableRow .button {border:0; padding : 0 0.2em}\n";
config.shadowTiddlers.StyleSheetFieldsEditor +="/*}}}*/";
store.addNotification("StyleSheetFieldsEditor", refreshStyles);

//}}}
一直習慣在firefox上用tiddlywiki,自從FF昇級到3.X的版本後,每次保存tiddlywiki都會出現一個"來自「f」的 Script 要求更高的權限 "的warning, 很討厭這個惱人的小視窗.
今天在tiddlywiki的官網上看到一篇文,講到的這個問題,試了幾遍,終於把這個小問題決了.

修改D:\bobe\PortableAPP\FirefoxPortable\App\DefaultData\profile\prefs.js (記得先備份.js)找到以下這二行
user_pref("capability.principal.codebase.p0.granted", "UniversalXPConnect UniversalBrowserRead");
user_pref("capability.principal.codebase.p0.id", "file://");
把user_pref("capability.principal.codebase.p0.id", "file://"); 改成user_pref("capability.principal.codebase.p0.id", "file://C:/BEV/Wiki/PrinceTiddly/BevTips/index.html");
如果你有許多不同的tiddly file, 你就要一個一個加入這二行,把實體路徑一一指定上去
像我有三個檔,就要加入以下這幾行
user_pref("capability.principal.codebase.p0.granted", "UniversalXPConnect UniversalBrowserRead");
user_pref("capability.principal.codebase.p0.id", "file://C:/BEV/Wiki/tiddlyWiki/BEV/BevWiki.html#Home");
user_pref("capability.principal.codebase.p1.granted", "UniversalXPConnect");
user_pref("capability.principal.codebase.p1.id", "file://C:/BEV/Wiki/tiddlyWiki/Projects/2008/SR2008.html");
user_pref("capability.principal.codebase.p1.subjectName", "");
user_pref("capability.principal.codebase.p2.granted", "UniversalXPConnect");
user_pref("capability.principal.codebase.p2.id", "file://C:/BEV/Wiki/PrinceTiddly/BevTips/index.html");
user_pref("capability.principal.codebase.p2.subjectName", ""); 

''prefs.js 檔案內容''
{{{
# Mozilla User Preferences

/* Do not edit this file.
 *
 * If you make changes to this file while the browser is running,
 * the changes will be overwritten when the browser exits.
 *
 * To make a manual change to preferences, you can visit the URL about:config
 * For more information, see http://www.mozilla.org/unix/customizing.html#prefs
 */

user_pref("app.update.auto", false);
user_pref("browser.cache.disk.capacity", 0);
user_pref("browser.download.useDownloadDir", false);
user_pref("browser.shell.checkDefaultBrowser", false);
user_pref("network.cookie.prefsMigrated", true);
}}}
/***
|''Name:''|ForEachTiddlerPlugin|
|''Version:''|1.0.8 (2007-04-12)|
|''Source:''|http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''Copyright:''|&copy; 2005-2007 [[abego Software|http://www.abego-software.de]]|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|
!Description

Create customizable lists, tables etc. for your selections of tiddlers. Specify the tiddlers to include and their order through a powerful language.

''Syntax:'' 
|>|{{{<<}}}''forEachTiddler'' [''in'' //tiddlyWikiPath//] [''where'' //whereCondition//] [''sortBy'' //sortExpression// [''ascending'' //or// ''descending'']] [''script'' //scriptText//] [//action// [//actionParameters//]]{{{>>}}}|
|//tiddlyWikiPath//|The filepath to the TiddlyWiki the macro should work on. When missing the current TiddlyWiki is used.|
|//whereCondition//|(quoted) JavaScript boolean expression. May refer to the build-in variables {{{tiddler}}} and  {{{context}}}.|
|//sortExpression//|(quoted) JavaScript expression returning "comparable" objects (using '{{{<}}}','{{{>}}}','{{{==}}}'. May refer to the build-in variables {{{tiddler}}} and  {{{context}}}.|
|//scriptText//|(quoted) JavaScript text. Typically defines JavaScript functions that are called by the various JavaScript expressions (whereClause, sortClause, action arguments,...)|
|//action//|The action that should be performed on every selected tiddler, in the given order. By default the actions [[addToList|AddToListAction]] and [[write|WriteAction]] are supported. When no action is specified [[addToList|AddToListAction]]  is used.|
|//actionParameters//|(action specific) parameters the action may refer while processing the tiddlers (see action descriptions for details). <<tiddler [[JavaScript in actionParameters]]>>|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|

See details see [[ForEachTiddlerMacro]] and [[ForEachTiddlerExamples]].

!Code
***/
//{{{

	
//============================================================================
//============================================================================
//		   ForEachTiddlerPlugin
//============================================================================
//============================================================================

// Only install once
if (!version.extensions.ForEachTiddlerPlugin) {

if (!window.abego) window.abego = {};

version.extensions.ForEachTiddlerPlugin = {
	major: 1, minor: 0, revision: 8, 
	date: new Date(2007,3,12), 
	source: "http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin",
	licence: "[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]",
	copyright: "Copyright (c) abego Software GmbH, 2005-2007 (www.abego-software.de)"
};

// For backward compatibility with TW 1.2.x
//
if (!TiddlyWiki.prototype.forEachTiddler) {
	TiddlyWiki.prototype.forEachTiddler = function(callback) {
		for(var t in this.tiddlers) {
			callback.call(this,t,this.tiddlers[t]);
		}
	};
}

//============================================================================
// forEachTiddler Macro
//============================================================================

version.extensions.forEachTiddler = {
	major: 1, minor: 0, revision: 8, date: new Date(2007,3,12), provider: "http://tiddlywiki.abego-software.de"};

// ---------------------------------------------------------------------------
// Configurations and constants 
// ---------------------------------------------------------------------------

config.macros.forEachTiddler = {
	 // Standard Properties
	 label: "forEachTiddler",
	 prompt: "Perform actions on a (sorted) selection of tiddlers",

	 // actions
	 actions: {
		 addToList: {},
		 write: {}
	 }
};

// ---------------------------------------------------------------------------
//  The forEachTiddler Macro Handler 
// ---------------------------------------------------------------------------

config.macros.forEachTiddler.getContainingTiddler = function(e) {
	while(e && !hasClass(e,"tiddler"))
		e = e.parentNode;
	var title = e ? e.getAttribute("tiddler") : null; 
	return title ? store.getTiddler(title) : null;
};

config.macros.forEachTiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
	// config.macros.forEachTiddler.traceMacroCall(place,macroName,params,wikifier,paramString,tiddler);

	if (!tiddler) tiddler = config.macros.forEachTiddler.getContainingTiddler(place);
	// --- Parsing ------------------------------------------

	var i = 0; // index running over the params
	// Parse the "in" clause
	var tiddlyWikiPath = undefined;
	if ((i < params.length) && params[i] == "in") {
		i++;
		if (i >= params.length) {
			this.handleError(place, "TiddlyWiki path expected behind 'in'.");
			return;
		}
		tiddlyWikiPath = this.paramEncode((i < params.length) ? params[i] : "");
		i++;
	}

	// Parse the where clause
	var whereClause ="true";
	if ((i < params.length) && params[i] == "where") {
		i++;
		whereClause = this.paramEncode((i < params.length) ? params[i] : "");
		i++;
	}

	// Parse the sort stuff
	var sortClause = null;
	var sortAscending = true; 
	if ((i < params.length) && params[i] == "sortBy") {
		i++;
		if (i >= params.length) {
			this.handleError(place, "sortClause missing behind 'sortBy'.");
			return;
		}
		sortClause = this.paramEncode(params[i]);
		i++;

		if ((i < params.length) && (params[i] == "ascending" || params[i] == "descending")) {
			 sortAscending = params[i] == "ascending";
			 i++;
		}
	}

	// Parse the script
	var scriptText = null;
	if ((i < params.length) && params[i] == "script") {
		i++;
		scriptText = this.paramEncode((i < params.length) ? params[i] : "");
		i++;
	}

	// Parse the action. 
	// When we are already at the end use the default action
	var actionName = "addToList";
	if (i < params.length) {
	   if (!config.macros.forEachTiddler.actions[params[i]]) {
			this.handleError(place, "Unknown action '"+params[i]+"'.");
			return;
		} else {
			actionName = params[i]; 
			i++;
		}
	} 
	
	// Get the action parameter
	// (the parsing is done inside the individual action implementation.)
	var actionParameter = params.slice(i);


	// --- Processing ------------------------------------------
	try {
		this.performMacro({
				place: place, 
				inTiddler: tiddler,
				whereClause: whereClause, 
				sortClause: sortClause, 
				sortAscending: sortAscending, 
				actionName: actionName, 
				actionParameter: actionParameter, 
				scriptText: scriptText, 
				tiddlyWikiPath: tiddlyWikiPath});

	} catch (e) {
		this.handleError(place, e);
	}
};

// Returns an object with properties "tiddlers" and "context".
// tiddlers holds the (sorted) tiddlers selected by the parameter,
// context the context of the execution of the macro.
//
// The action is not yet performed.
//
// @parameter see performMacro
//
config.macros.forEachTiddler.getTiddlersAndContext = function(parameter) {

	var context = config.macros.forEachTiddler.createContext(parameter.place, parameter.whereClause, parameter.sortClause, parameter.sortAscending, parameter.actionName, parameter.actionParameter, parameter.scriptText, parameter.tiddlyWikiPath, parameter.inTiddler);

	var tiddlyWiki = parameter.tiddlyWikiPath ? this.loadTiddlyWiki(parameter.tiddlyWikiPath) : store;
	context["tiddlyWiki"] = tiddlyWiki;
	
	// Get the tiddlers, as defined by the whereClause
	var tiddlers = this.findTiddlers(parameter.whereClause, context, tiddlyWiki);
	context["tiddlers"] = tiddlers;

	// Sort the tiddlers, when sorting is required.
	if (parameter.sortClause) {
		this.sortTiddlers(tiddlers, parameter.sortClause, parameter.sortAscending, context);
	}

	return {tiddlers: tiddlers, context: context};
};

// Returns the (sorted) tiddlers selected by the parameter.
//
// The action is not yet performed.
//
// @parameter see performMacro
//
config.macros.forEachTiddler.getTiddlers = function(parameter) {
	return this.getTiddlersAndContext(parameter).tiddlers;
};

// Performs the macros with the given parameter.
//
// @param parameter holds the parameter of the macro as separate properties.
//				  The following properties are supported:
//
//						place
//						whereClause
//						sortClause
//						sortAscending
//						actionName
//						actionParameter
//						scriptText
//						tiddlyWikiPath
//
//					All properties are optional. 
//					For most actions the place property must be defined.
//
config.macros.forEachTiddler.performMacro = function(parameter) {
	var tiddlersAndContext = this.getTiddlersAndContext(parameter);

	// Perform the action
	var actionName = parameter.actionName ? parameter.actionName : "addToList";
	var action = config.macros.forEachTiddler.actions[actionName];
	if (!action) {
		this.handleError(parameter.place, "Unknown action '"+actionName+"'.");
		return;
	}

	var actionHandler = action.handler;
	actionHandler(parameter.place, tiddlersAndContext.tiddlers, parameter.actionParameter, tiddlersAndContext.context);
};

// ---------------------------------------------------------------------------
//  The actions 
// ---------------------------------------------------------------------------

// Internal.
//
// --- The addToList Action -----------------------------------------------
//
config.macros.forEachTiddler.actions.addToList.handler = function(place, tiddlers, parameter, context) {
	// Parse the parameter
	var p = 0;

	// Check for extra parameters
	if (parameter.length > p) {
		config.macros.forEachTiddler.createExtraParameterErrorElement(place, "addToList", parameter, p);
		return;
	}

	// Perform the action.
	var list = document.createElement("ul");
	place.appendChild(list);
	for (var i = 0; i < tiddlers.length; i++) {
		var tiddler = tiddlers[i];
		var listItem = document.createElement("li");
		list.appendChild(listItem);
		createTiddlyLink(listItem, tiddler.title, true);
	}
};

abego.parseNamedParameter = function(name, parameter, i) {
	var beginExpression = null;
	if ((i < parameter.length) && parameter[i] == name) {
		i++;
		if (i >= parameter.length) {
			throw "Missing text behind '%0'".format([name]);
		}
		
		return config.macros.forEachTiddler.paramEncode(parameter[i]);
	}
	return null;
}

// Internal.
//
// --- The write Action ---------------------------------------------------
//
config.macros.forEachTiddler.actions.write.handler = function(place, tiddlers, parameter, context) {
	// Parse the parameter
	var p = 0;
	if (p >= parameter.length) {
		this.handleError(place, "Missing expression behind 'write'.");
		return;
	}

	var textExpression = config.macros.forEachTiddler.paramEncode(parameter[p]);
	p++;

	// Parse the "begin" option
	var beginExpression = abego.parseNamedParameter("begin", parameter, p);
	if (beginExpression !== null) 
		p += 2;
	var endExpression = abego.parseNamedParameter("end", parameter, p);
	if (endExpression !== null) 
		p += 2;
	var noneExpression = abego.parseNamedParameter("none", parameter, p);
	if (noneExpression !== null) 
		p += 2;

	// Parse the "toFile" option
	var filename = null;
	var lineSeparator = undefined;
	if ((p < parameter.length) && parameter[p] == "toFile") {
		p++;
		if (p >= parameter.length) {
			this.handleError(place, "Filename expected behind 'toFile' of 'write' action.");
			return;
		}
		
		filename = config.macros.forEachTiddler.getLocalPath(config.macros.forEachTiddler.paramEncode(parameter[p]));
		p++;
		if ((p < parameter.length) && parameter[p] == "withLineSeparator") {
			p++;
			if (p >= parameter.length) {
				this.handleError(place, "Line separator text expected behind 'withLineSeparator' of 'write' action.");
				return;
			}
			lineSeparator = config.macros.forEachTiddler.paramEncode(parameter[p]);
			p++;
		}
	}
	
	// Check for extra parameters
	if (parameter.length > p) {
		config.macros.forEachTiddler.createExtraParameterErrorElement(place, "write", parameter, p);
		return;
	}

	// Perform the action.
	var func = config.macros.forEachTiddler.getEvalTiddlerFunction(textExpression, context);
	var count = tiddlers.length;
	var text = "";
	if (count > 0 && beginExpression)
		text += config.macros.forEachTiddler.getEvalTiddlerFunction(beginExpression, context)(undefined, context, count, undefined);
	
	for (var i = 0; i < count; i++) {
		var tiddler = tiddlers[i];
		text += func(tiddler, context, count, i);
	}
	
	if (count > 0 && endExpression)
		text += config.macros.forEachTiddler.getEvalTiddlerFunction(endExpression, context)(undefined, context, count, undefined);

	if (count == 0 && noneExpression) 
		text += config.macros.forEachTiddler.getEvalTiddlerFunction(noneExpression, context)(undefined, context, count, undefined);
		

	if (filename) {
		if (lineSeparator !== undefined) {
			lineSeparator = lineSeparator.replace(/\\n/mg, "\n").replace(/\\r/mg, "\r");
			text = text.replace(/\n/mg,lineSeparator);
		}
		saveFile(filename, convertUnicodeToUTF8(text));
	} else {
		var wrapper = createTiddlyElement(place, "span");
		wikify(text, wrapper, null/* highlightRegExp */, context.inTiddler);
	}
};


// ---------------------------------------------------------------------------
//  Helpers
// ---------------------------------------------------------------------------

// Internal.
//
config.macros.forEachTiddler.createContext = function(placeParam, whereClauseParam, sortClauseParam, sortAscendingParam, actionNameParam, actionParameterParam, scriptText, tiddlyWikiPathParam, inTiddlerParam) {
	return {
		place : placeParam, 
		whereClause : whereClauseParam, 
		sortClause : sortClauseParam, 
		sortAscending : sortAscendingParam, 
		script : scriptText,
		actionName : actionNameParam, 
		actionParameter : actionParameterParam,
		tiddlyWikiPath : tiddlyWikiPathParam,
		inTiddler : inTiddlerParam, // the tiddler containing the <<forEachTiddler ...>> macro call.
		viewerTiddler : config.macros.forEachTiddler.getContainingTiddler(placeParam) // the tiddler showing the forEachTiddler result
	};
};

// Internal.
//
// Returns a TiddlyWiki with the tiddlers loaded from the TiddlyWiki of 
// the given path.
//
config.macros.forEachTiddler.loadTiddlyWiki = function(path, idPrefix) {
	if (!idPrefix) {
		idPrefix = "store";
	}
	var lenPrefix = idPrefix.length;
	
	// Read the content of the given file
	var content = loadFile(this.getLocalPath(path));
	if(content === null) {
		throw "TiddlyWiki '"+path+"' not found.";
	}
	
	var tiddlyWiki = new TiddlyWiki();

	// Starting with TW 2.2 there is a helper function to import the tiddlers
	if (tiddlyWiki.importTiddlyWiki) {
		if (!tiddlyWiki.importTiddlyWiki(content))
			throw "File '"+path+"' is not a TiddlyWiki.";
		tiddlyWiki.dirty = false;
		return tiddlyWiki;
	}
	
	// The legacy code, for TW < 2.2
	
	// Locate the storeArea div's
	var posOpeningDiv = content.indexOf(startSaveArea);
	var posClosingDiv = content.lastIndexOf(endSaveArea);
	if((posOpeningDiv == -1) || (posClosingDiv == -1)) {
		throw "File '"+path+"' is not a TiddlyWiki.";
	}
	var storageText = content.substr(posOpeningDiv + startSaveArea.length, posClosingDiv);
	
	// Create a "div" element that contains the storage text
	var myStorageDiv = document.createElement("div");
	myStorageDiv.innerHTML = storageText;
	myStorageDiv.normalize();
	
	// Create all tiddlers in a new TiddlyWiki
	// (following code is modified copy of TiddlyWiki.prototype.loadFromDiv)
	var store = myStorageDiv.childNodes;
	for(var t = 0; t < store.length; t++) {
		var e = store[t];
		var title = null;
		if(e.getAttribute)
			title = e.getAttribute("tiddler");
		if(!title && e.id && e.id.substr(0,lenPrefix) == idPrefix)
			title = e.id.substr(lenPrefix);
		if(title && title !== "") {
			var tiddler = tiddlyWiki.createTiddler(title);
			tiddler.loadFromDiv(e,title);
		}
	}
	tiddlyWiki.dirty = false;

	return tiddlyWiki;
};


	
// Internal.
//
// Returns a function that has a function body returning the given javaScriptExpression.
// The function has the parameters:
// 
//	 (tiddler, context, count, index)
//
config.macros.forEachTiddler.getEvalTiddlerFunction = function (javaScriptExpression, context) {
	var script = context["script"];
	var functionText = "var theFunction = function(tiddler, context, count, index) { return "+javaScriptExpression+"}";
	var fullText = (script ? script+";" : "")+functionText+";theFunction;";
	return eval(fullText);
};

// Internal.
//
config.macros.forEachTiddler.findTiddlers = function(whereClause, context, tiddlyWiki) {
	var result = [];
	var func = config.macros.forEachTiddler.getEvalTiddlerFunction(whereClause, context);
	tiddlyWiki.forEachTiddler(function(title,tiddler) {
		if (func(tiddler, context, undefined, undefined)) {
			result.push(tiddler);
		}
	});
	return result;
};

// Internal.
//
config.macros.forEachTiddler.createExtraParameterErrorElement = function(place, actionName, parameter, firstUnusedIndex) {
	var message = "Extra parameter behind '"+actionName+"':";
	for (var i = firstUnusedIndex; i < parameter.length; i++) {
		message += " "+parameter[i];
	}
	this.handleError(place, message);
};

// Internal.
//
config.macros.forEachTiddler.sortAscending = function(tiddlerA, tiddlerB) {
	var result = 
		(tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue) 
			? 0
			: (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)
			   ? -1 
			   : +1; 
	return result;
};

// Internal.
//
config.macros.forEachTiddler.sortDescending = function(tiddlerA, tiddlerB) {
	var result = 
		(tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue) 
			? 0
			: (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)
			   ? +1 
			   : -1; 
	return result;
};

// Internal.
//
config.macros.forEachTiddler.sortTiddlers = function(tiddlers, sortClause, ascending, context) {
	// To avoid evaluating the sortClause whenever two items are compared 
	// we pre-calculate the sortValue for every item in the array and store it in a 
	// temporary property ("forEachTiddlerSortValue") of the tiddlers.
	var func = config.macros.forEachTiddler.getEvalTiddlerFunction(sortClause, context);
	var count = tiddlers.length;
	var i;
	for (i = 0; i < count; i++) {
		var tiddler = tiddlers[i];
		tiddler.forEachTiddlerSortValue = func(tiddler,context, undefined, undefined);
	}

	// Do the sorting
	tiddlers.sort(ascending ? this.sortAscending : this.sortDescending);

	// Delete the temporary property that holds the sortValue.	
	for (i = 0; i < tiddlers.length; i++) {
		delete tiddlers[i].forEachTiddlerSortValue;
	}
};


// Internal.
//
config.macros.forEachTiddler.trace = function(message) {
	displayMessage(message);
};

// Internal.
//
config.macros.forEachTiddler.traceMacroCall = function(place,macroName,params) {
	var message ="<<"+macroName;
	for (var i = 0; i < params.length; i++) {
		message += " "+params[i];
	}
	message += ">>";
	displayMessage(message);
};


// Internal.
//
// Creates an element that holds an error message
// 
config.macros.forEachTiddler.createErrorElement = function(place, exception) {
	var message = (exception.description) ? exception.description : exception.toString();
	return createTiddlyElement(place,"span",null,"forEachTiddlerError","<<forEachTiddler ...>>: "+message);
};

// Internal.
//
// @param place [may be null]
//
config.macros.forEachTiddler.handleError = function(place, exception) {
	if (place) {
		this.createErrorElement(place, exception);
	} else {
		throw exception;
	}
};

// Internal.
//
// Encodes the given string.
//
// Replaces 
//	 "$))" to ">>"
//	 "$)" to ">"
//
config.macros.forEachTiddler.paramEncode = function(s) {
	var reGTGT = new RegExp("\\$\\)\\)","mg");
	var reGT = new RegExp("\\$\\)","mg");
	return s.replace(reGTGT, ">>").replace(reGT, ">");
};

// Internal.
//
// Returns the given original path (that is a file path, starting with "file:")
// as a path to a local file, in the systems native file format.
//
// Location information in the originalPath (i.e. the "#" and stuff following)
// is stripped.
// 
config.macros.forEachTiddler.getLocalPath = function(originalPath) {
	// Remove any location part of the URL
	var hashPos = originalPath.indexOf("#");
	if(hashPos != -1)
		originalPath = originalPath.substr(0,hashPos);
	// Convert to a native file format assuming
	// "file:///x:/path/path/path..." - pc local file --> "x:\path\path\path..."
	// "file://///server/share/path/path/path..." - FireFox pc network file --> "\\server\share\path\path\path..."
	// "file:///path/path/path..." - mac/unix local file --> "/path/path/path..."
	// "file://server/share/path/path/path..." - pc network file --> "\\server\share\path\path\path..."
	var localPath;
	if(originalPath.charAt(9) == ":") // pc local file
		localPath = unescape(originalPath.substr(8)).replace(new RegExp("/","g"),"\\");
	else if(originalPath.indexOf("file://///") === 0) // FireFox pc network file
		localPath = "\\\\" + unescape(originalPath.substr(10)).replace(new RegExp("/","g"),"\\");
	else if(originalPath.indexOf("file:///") === 0) // mac/unix local file
		localPath = unescape(originalPath.substr(7));
	else if(originalPath.indexOf("file:/") === 0) // mac/unix local file
		localPath = unescape(originalPath.substr(5));
	else // pc network file
		localPath = "\\\\" + unescape(originalPath.substr(7)).replace(new RegExp("/","g"),"\\");	
	return localPath;
};

// ---------------------------------------------------------------------------
// Stylesheet Extensions (may be overridden by local StyleSheet)
// ---------------------------------------------------------------------------
//
setStylesheet(
	".forEachTiddlerError{color: #ffffff;background-color: #880000;}",
	"forEachTiddler");

//============================================================================
// End of forEachTiddler Macro
//============================================================================


//============================================================================
// String.startsWith Function
//============================================================================
//
// Returns true if the string starts with the given prefix, false otherwise.
//
version.extensions["String.startsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.startsWith = function(prefix) {
	var n =  prefix.length;
	return (this.length >= n) && (this.slice(0, n) == prefix);
};



//============================================================================
// String.endsWith Function
//============================================================================
//
// Returns true if the string ends with the given suffix, false otherwise.
//
version.extensions["String.endsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.endsWith = function(suffix) {
	var n = suffix.length;
	return (this.length >= n) && (this.right(n) == suffix);
};


//============================================================================
// String.contains Function
//============================================================================
//
// Returns true when the string contains the given substring, false otherwise.
//
version.extensions["String.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.contains = function(substring) {
	return this.indexOf(substring) >= 0;
};

//============================================================================
// Array.indexOf Function
//============================================================================
//
// Returns the index of the first occurance of the given item in the array or 
// -1 when no such item exists.
//
// @param item [may be null]
//
version.extensions["Array.indexOf"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.indexOf = function(item) {
	for (var i = 0; i < this.length; i++) {
		if (this[i] == item) {
			return i;
		}
	}
	return -1;
};

//============================================================================
// Array.contains Function
//============================================================================
//
// Returns true when the array contains the given item, otherwise false. 
//
// @param item [may be null]
//
version.extensions["Array.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.contains = function(item) {
	return (this.indexOf(item) >= 0);
};

//============================================================================
// Array.containsAny Function
//============================================================================
//
// Returns true when the array contains at least one of the elements 
// of the item. Otherwise (or when items contains no elements) false is returned.
//
version.extensions["Array.containsAny"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.containsAny = function(items) {
	for(var i = 0; i < items.length; i++) {
		if (this.contains(items[i])) {
			return true;
		}
	}
	return false;
};


//============================================================================
// Array.containsAll Function
//============================================================================
//
// Returns true when the array contains all the items, otherwise false.
// 
// When items is null false is returned (even if the array contains a null).
//
// @param items [may be null] 
//
version.extensions["Array.containsAll"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.containsAll = function(items) {
	for(var i = 0; i < items.length; i++) {
		if (!this.contains(items[i])) {
			return false;
		}
	}
	return true;
};


} // of "install only once"

// Used Globals (for JSLint) ==============
// ... DOM
/*global 	document */
// ... TiddlyWiki Core
/*global 	convertUnicodeToUTF8, createTiddlyElement, createTiddlyLink, 
			displayMessage, endSaveArea, hasClass, loadFile, saveFile, 
			startSaveArea, store, wikify */
//}}}


/***
!Licence and Copyright
Copyright (c) abego Software ~GmbH, 2005 ([[www.abego-software.de|http://www.abego-software.de]])

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.

Neither the name of abego Software nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
***/
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler  -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='easyEdit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<!--}}}-->
/***
|Name|HTMLFormattingPlugin|
|Source|http://www.TiddlyTools.com/#HTMLFormattingPlugin|
|Documentation|http://www.TiddlyTools.com/#HTMLFormattingPluginInfo|
|Version|2.1.5|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|'HTML' formatter|
|Description|embed wiki syntax formatting inside of HTML content|
The shorthand Wiki-style formatting syntax of ~TiddlyWiki is very convenient and enables most content to be reasonably well presented. However, there are times when tried-and-true HTML formatting syntax allows more more precise control of the content display.  When HTML formatting syntax is embedded within a tiddler (in between {{{<}}}{{{html>}}} and {{{<}}}{{{/html>}}} markers) TiddlyWiki passes this content to the browser for processing as 'native' HTML.  However, TiddlyWiki does not also process the HTML source content for any embedded wiki-formatting syntax it may contain.  This means that while you can use HTML formatted content, you cannot mix wiki-formatted content within the HTML formatting.

The ~HTMLFormatting plugin allows you to freely ''mix wiki-style formatting syntax within HTML formatted content'' by extending the action of the standard TiddlyWiki formatting handler.
!!!!!Documentation
>see [[HTMLFormattingPluginInfo]]
!!!!!Revisions
<<<
2008.01.08 [*.*.*] plugin size reduction: documentation moved to HTMLFormattingInfo
2007.12.04 [*.*.*] update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.06.14 [2.1.5] in formatter, removed call to e.normalize().  Creates an INFINITE RECURSION error in Safari!!!!
2006.09.10 [2.1.4] update formatter for 2.1 compatibility (use this.lookaheadRegExp instead of temp variable)
2006.05.28 [2.1.3] in wikifyTextNodes(), decode the *value* of TEXTAREA nodes, but don't wikify() its children.  (thanks to "ayj" for bug report)
2006.02.19 [2.1.2] in wikifyTextNodes(), put SPAN element into tiddler DOM (replacing text node), BEFORE wikifying the text content.  This ensures that the 'place' passed to any macros is correctly defined when the macro is evaluated, so that calls to story.findContainingTiddler(place) will work as expected. (Thanks for bug report from GeoffSlocock)
2006.02.05 [2.1.1] wrapped wikifier hijack in init function to eliminate globals and avoid FireFox 1.5.0.1 crash bug when referencing globals
2005.12.01 [2.1.0] don't wikify #TEXT nodes inside SELECT and TEXTAREA elements
2005.11.06 [2.0.1] code cleanup
2005.10.31 [2.0.0] replaced hijack wikify() with hijack config.formatters["html"] and simplified recursive WikifyTextNodes() code
2005.10.09 [1.0.2] combined documentation and code into a single tiddler
2005.08.05 [1.0.1] moved HTML and CSS definitions into plugin code instead of using separate tiddlers
2005.07.26 [1.0.1] Re-released as a plugin. Added <{{{html}}}>...</{{{nohtml}}}> and <{{{hide newlines}}}> handling
2005.06.26 [1.0.0] Initial Release (as code adaptation - pre-dates TiddlyWiki plugin architecture!!)
<<<
!!!!!Code
***/
//{{{
version.extensions.HTMLFormatting = {major: 2, minor: 1, revision: 5, date: new Date(2007,6,14)};

// find the formatter for HTML and replace the handler
initHTMLFormatter();
function initHTMLFormatter()
{
	for (var i=0; i<config.formatters.length && config.formatters[i].name!="html"; i++);
	if (i<config.formatters.length)	config.formatters[i].handler=function(w) {
		if (!this.lookaheadRegExp)  // fixup for TW2.0.x
			this.lookaheadRegExp = new RegExp(this.lookahead,"mg");
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
			var html=lookaheadMatch[1];
			// optionally suppress wiki-style literal handling of newlines
			// strip any carriage returns added by Internet Explorer's textarea edit field
			// encode newlines as \n so Internet Explorer's HTML parser won't eat them
			// encode macro brackets (<< and >>) so HTML parser won't eat them
			if (html.indexOf('<hide linebreaks>')!=-1) html=html.replace(/\n/g,' ');
			html=html.replace(/\r/g,'');
			html=html.replace(/\n/g,'\\n');
			html=html.replace(/<</g,'%%(').replace(/>>/g,')%%');
			// create span to hold HTML
			// parse HTML and normalize the results
			// walk node tree and call wikify() on each text node
			var e = createTiddlyElement(w.output,"span");
			e.innerHTML=html;
			// REMOVED: e.normalize();  // THIS CAUSED INFINITE RECURSION IN SAFARI
			wikifyTextNodes(e);
			// advance to next parse position
			w.nextMatch = this.lookaheadRegExp.lastIndex;
		}
	}
}

// wikify text nodes remaining after HTML content is processed (pre-order recursion)
function wikifyTextNodes(theNode)
{
	// textarea node doesn't get wikified, just decoded... 
	if (theNode.nodeName.toLowerCase()=='textarea')
		theNode.value=theNode.value.replace(/\%%\(/g,'<<').replace(/\)\%%/g,'>>').replace(/\\n/g,'\n');
	else for (var i=0;i<theNode.childNodes.length;i++) {
		var theChild=theNode.childNodes.item(i);
		if (theChild.nodeName.toLowerCase()=='option') continue;
		if (theChild.nodeName.toLowerCase()=='select') continue;
		wikifyTextNodes(theChild);
		if (theChild.nodeName=='#text') {
			var txt=theChild.nodeValue;
			// decode macro brackets and newlines
			txt=txt.replace(/\%%\(/g,'<<').replace(/\)\%%/g,'>>').replace(/\\n/g,'\n');
			// replace text node with wikified() span
			var newNode=createTiddlyElement(null,"span");
			theNode.replaceChild(newNode,theChild);
			wikify(txt,newNode);
		}
	}
}
//}}}
<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +easyEdit > fields syncing permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>

<!--
<div class='tagging' macro='tagging'></div>
-->
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
本文網址 : http://www.ithome.com.tw/itadm/article.php?c=59343

在中研院資科所擔任助研究員的陳昇瑋,卸下過去的名聲、只帶著多年累積的開發能力,一心勇闖學術界,以便更自在地鑽研開發所喜好的技術主題,並追求無人可取代的自我價值 

中央研究院資訊科學研究所助研究員/多媒體網路與系統實驗室主持人

1976年生
●學經歷:臺灣大學電機工程博士,於清華大學資訊工程系取得碩士與學士。原名陳寬達,曾擔任 Windows 及系統程式設計師、業界程式設計課程講師、技術書籍及雜誌專欄作者、共享軟體作者及 BBS 開發者/站長等工作,並著有《Delphi 深度歷險》、《C++Builder 深度歷險》等書
●個人的中文網站連結網址:www.iis.sinica.edu.tw/~swc/index_c.html
	
 

假如想撰寫Windows程式碼,Delphi、C++ Builder是一直是過去許多人心中的首選,而在推廣這個開發環境裡最知名的人物中,有一位很引人注目,那就是陳昇瑋(先前他的名字叫做陳寬達)。他既是兩本相關電腦書籍的作者,十多年前,也和同樣熱中於程式開發的錢達智,一起創辦了DelphiChat/BCBChat電子郵件討論群(即 Programmer 深度論壇網站的前身)。

學生時代即嶄露頭角
事實上,早在清華大學資訊科學系就讀期間,陳昇瑋已經開始投入很多心力在IT上,像是擔任楓橋驛站BBS的站長,負責站務維護與程式發展,同時也成立 Delphi和C++ Builder的程式設計技術討論社群。至於當時非程式開發的進階使用者而言,也可能聽過他這號人物,例如他曾經擔任HopeNet光碟月刊的技術編輯,負責精選許多好用的共享軟體與免費軟體,此外,他自己也寫出好幾套遠近馳名的共享軟體,像是XDesktop、XthemeManager、XMP3 Manager、XViewer、Xchat(當時他在網路上的暱稱叫做Xshadow)。

歷經許多令人津津樂道的事蹟,然而在2000年以後,就越來越少從IT界聽到他的近況。原來,他當時決定選擇回到學術研究的領域,繼續完成研究生的學業、拿下博士學位,並以閱讀論文與發表研究成果為樂,而這樣的狀態和他現在的身分息息相關──中央研究院的資訊科學研究所助研究員(等同於大學裡的助理教授),同時主持了多媒體網路與系統實驗室。

尋找無可替代的自我價值
陳昇瑋之所以離開IT領域、走到學術的懷抱,他提到有下列幾個原因。

首先,就像許多IT人所認為的,單靠IT來謀生太辛苦,需要花很大的力氣,而且似乎永遠無法停止腳步休息。

對於工作這檔事,陳昇瑋原本打算用SOHO的方式講課和接案。於是他到中科院、園區和資策會,主講關於開發的課程,但他後來看到即使本身經營得相當成功的前輩,仍然得戰戰兢兢地工作著,才能將生活過好,因為不工作,就不會有錢。他認為,這樣就像《富爸爸,窮爸爸》書中所說,消費模式是花辛苦賺來的每一分錢,只能靠節約費用和儲蓄,而無法獲得財務和生活上的自由。

等他投身學術之後,雖然收入變少、薪資變固定,但他很清楚所要的目標和生活,為了更專注在這些事情上,因此也不再接案,該休息的時候就休息,不讓自己受到外務影響。

離開既有生活的第二個理由是,技術上雖然一直在進步、相關的名詞不斷推陳出新,但工作過程中令他覺得興奮的大突破,似乎越來越少,許多應用的原理法則和底層架構,幾乎都是萬變不離其宗。他所面臨的是更多非技術上的挑戰,像是受限於人力、時間與資源的配置,花費很多心力、體力在開會協調,而非完全專注在IT 開發或疑難排解上。

最後也最關鍵的考量是,陳昇瑋理解到在很多工作當中,「你」很重要,但沒有「你」,也還是能做到。

每個人可能在公司工作得很愉快、很有成就感,但根據他的觀察及周遭同學的經驗,他發現若有一天被裁員,原本該進行的工作,還是會繼續,公司仍然可以賺錢或研發出新的產品。

綜合這些考量,他決定尋找別的出路。也因為當時在念碩士班,在學術研究當中,他找到最能滿足自身理想的答案。

在研究的領域,陳昇瑋認為其實有趣的議題非常多,絕對不用擔心做完,而且可以完全由自己主導──有些偏重理論性的議題,只要一個人作即可,即使是實作型的題目,自己帶領兩三個學生就可以研究。

從這樣的歷程來看,陳昇瑋最想要做的是具有獨創和原創特性的事情,一旦達到他所預期的成效,會讓他更清楚地知道「沒有我,就沒有這個研究」,因為挑戰無窮,所以覺得每天都過得非常充實,而且明白自己的價值。

成為學者,他不光研究理論,也捲起袖子繼續寫程式
在電腦科學的領域,有人專攻理論,而陳昇瑋最近主要的研究對象,是關於Skype、MSN Messenger等即時通訊軟體的語音品質和視訊品質,他在去年曾發表關於量測Skype使用者滿意度的方法,而要做到這件事,必須要靠寫程式來監看、量測網路應用程式的行為及效能。

在這樣的過程中,陳昇瑋說,程式一定要寫得夠快、夠有彈性,快是因為有些因素無法預測,必須要不斷想方法去嘗試、改進,因此程式開發功力和速度會非常重要,實驗進行的期間,他和參與學生們都必須克服這項挑戰。

由於陳昇瑋本身具有程式設計的實戰經驗累積,這難不倒他,但他要和所帶領的學生一起完成這項工作,所以如何提升整體戰力是當務之急,雖然他自認快十年沒有好好寫程式,不過要幫學生Debug、看出程式執行上有沒有效率,能否善用物件導向和事件驅動的概念來開發,他還是能一眼就看出好壞。

此外,他們並不需要特別去關注系統建置的平臺和解決方案。以視訊串流的實驗來說,若有系統提供最好用的函式庫,他們會想辦法搭配出來,因此有可能網路控制軟體會用FreeBSD來架設,而串流處理就用Windows或Linux。對他來說,一個實力堅強的Programmer,不會受限於任何工具、平臺,因為他們已經掌握了關鍵的概念、以及各平臺常用的技術,而且具有基本的演算法的掌握能力,若需要寫一個最短路徑(Shortest Path)或快速排序(Quick sort)等演算法,你隨時可以寫得出來,而不只是會用遞迴的方式來解開發需求。

將兩件事做到85分很厲害,但將一件事做到95分更重要
從完全投身IT界到完全投身學術界,作家劉墉說過的一段話影響陳昇瑋做了這個決定。這段話的意思是如果你今天在一個山頭上,看見另一個山頭想上去,第一件事得先下山,因為你不可能同時站在兩個山頭上,這是劉墉對於自己從中視記者毅然離開、成為作家的告白,對陳昇瑋也很感同身受,他只想完全歸零,連以前 BBS的ID(Xshadow)都不再使用。

對於決定人生的方向,他建議要想清楚之後就絕對不要改變,因為一個人絕對沒辦法同時站在兩個山頭,沒辦法同時做兩件事做到好。他眼中的「好」,是指登峰造極。如果能將兩件事做到85分,那表示很厲害,但將一件事做到95分更重要。

全心全意、專注心思很重要,他說:「如果要做到好、非常好,你一定要一次Focus在一件事。」,陳昇瑋從高中以後,很少花時間去看電視及報紙,但他發現其實不會錯過重要的訊息,因為在路上都會聽到別人耳語,或遇到人聊起相關議題,所以他決定不為那些事分心。相較之下,如果能聚精會神,把很重要的事作好,並且真正把自己的潛力發揮出來,他覺得是更美好的。

他說:「如果你有空跟別人說你很忙,如果你還記得打開BBS或開新聞網站的,那表示還不夠忙、不夠投入。」雖然沒必要365天都心無旁騖地工作或學習,但陳昇瑋認為,一個人若有潛力就該盡量發揮;除了要醞釀、收集情報和思考之外,也要努力將所知道的,加以創作、實現出來,這樣,創意才會源源不絕。文⊙李宗翰 
{{{
親愛的___總 / ___工程師:

    承蒙公司照顧,本人 _______ 自民國 ___ 年起服務於 ______ 公司,始終視公司永續成長為己任。
    
因此在得知保智大隊陸續針對企業盜版軟體展開搜查後,認為應善盡提醒責任,建議您儘早檢視公司軟體使用情形,以免公司在不知情的情況下面臨經營危機。
	
    根據過去法律訴訟結果顯示,公司因侵害著作權而遭起訴且判刑者,公司負責人及業務執行人員將背負3年以下有期徒刑,民事賠償金亦有高達上千萬元的紀錄。

    於公於私為了公司永續經營,以及保障本人的相關權益,建議您即刻編列預算進行軟體採購,補足合法軟體授權數,避免面臨刑事及民事風險。

感謝您撥冗閱讀,願能繼續與您共創佳績!              

	                                  祝公司 鴻圖大展 	


                                                                                                                                                _________ 敬上 
}}}
/***
|Name|ImportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ImportTiddlersPluginInfo|
|Version|4.3.3|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|config.macros.importTiddlers.handler|
|Description|interactive controls for import/export with filtering.|
This plugin lets you selectively combine tiddlers from any two TiddlyWiki documents.  An interactive control panel lets you pick a document to import from, and then select which tiddlers to import, with prompting for skip, rename, merge or replace actions when importing tiddlers that match existing titles.  Automatically add tags to imported tiddlers so they are easy to find later on.  Generates a detailed report of import 'history' in ImportedTiddlers.
***/
// // ''MACRO DEFINITION''
//{{{
// Version
version.extensions.importTiddlers = {major: 4, minor: 3, revision: 3, date: new Date(2008,8,12)};

// add ImportTiddlerPlugin controls to built-in backstage import task
if (config.tasks) { // TW2.2 or above
	config.tasks.importTask.content="<<tiddler ImportTiddlers>>"
}

// IE needs explicit global scoping for functions/vars called from browser events
window.onClickImportButton=onClickImportButton;
window.refreshImportList=refreshImportList;

// default cookie/option values
if (!config.options.chkImportReport) config.options.chkImportReport=true;

// default shadow definition
config.shadowTiddlers.ImportTiddlers="Use ~TiddlyWiki built-in importer (below) or, ";
config.shadowTiddlers.ImportTiddlers+="<<importTiddlers link 'Use ImportTiddlersPlugin control panel...'>>\n";
config.shadowTiddlers.ImportTiddlers+="<<importTiddlers core>>";

merge(config.macros.importTiddlers,{
	label: "import tiddlers",
	prompt: "Copy tiddlers from another document",
	openMsg: "Opening %0",
	openErrMsg: "Could not open %0 - error=%1",
	readMsg: "Read %0 bytes from %1",
	foundMsg: "Found %0 tiddlers in %1",
	filterMsg: "Filtered %0 tiddlers matching '%1'",
	summaryMsg: "%0 tiddler%1 in the list",
	summaryFilteredMsg: "%0 of %1 tiddler%2 in the list",
	plural: "s are",
	single: " is",
	countMsg: "%0 tiddlers selected for import",
	processedMsg: "Processed %0 tiddlers",
	importedMsg: "Imported %0 of %1 tiddlers from %2",
	loadText: "please load a document...",
	closeText: "close",	// text for close button when file is loaded
	doneText: "done",	// text for close button when file is not loaded
	startText: "import",	// text for import button
	stopText: "stop",	// text for import button while importing
	local: true,		// default to import from local file
	src: "",		// path/filename or URL of document to import (retrieved from SiteUrl tiddler)
	proxy: "",		// URL for remote proxy script (retrieved from SiteProxy tiddler)
	useProxy: false,	// use specific proxy script in front of remote URL
	inbound: null,		// hash-indexed array of tiddlers from other document
	newTags: "",		// text of tags added to imported tiddlers
	addTags: true,		// add new tags to imported tiddlers
	listsize: 10,		// # of lines to show in imported tiddler list
	importTags: true,	// include tags from remote source document when importing a tiddler
	keepTags: true,		// retain existing tags when replacing a tiddler
	sync: false,		// add 'server' fields to imported tiddlers (for sync function)
	lastFilter: "",		// most recent filter (URL hash) applied
	lastAction: null,	// most recent collision button performed
	index: 0,		// current processing index in import list
	sort: ""		// sort order for imported tiddler listbox
});

if (config.macros.importTiddlers.coreHandler==undefined)
	config.macros.importTiddlers.coreHandler=config.macros.importTiddlers.handler; // save built-in handler
config.macros.importTiddlers.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
	if (!params[0] || params[0].toLowerCase()=='core') { // default to built in
		if (config.macros.importTiddlers.coreHandler)
			config.macros.importTiddlers.coreHandler.apply(this,arguments);
		else 
			createTiddlyButton(place,this.label,this.prompt,onClickImportMenu);
	} else if (params[0]=='link') { // show link to floating panel
		createTiddlyButton(place,params[1]||this.label,params[2]||this.prompt,onClickImportMenu);
	} else if (params[0]=='inline') {// show panel as INLINE tiddler content
		createImportPanel(place);
		document.getElementById("importPanel").style.position="static";
		document.getElementById("importPanel").style.display="block";
	} else if (config.macros.loadTiddlers)
		config.macros.loadTiddlers.handler(place,macroName,params); // any other params: loadtiddlers
}

// // ''INTERFACE DEFINITION''
// // Handle link click to create/show/hide control panel
//{{{
function onClickImportMenu(e)
{
	if (!e) var e = window.event;
	var parent=resolveTarget(e).parentNode;
	var panel = document.getElementById("importPanel");
	if (panel==undefined || panel.parentNode!=parent)
		panel=createImportPanel(parent);
	var isOpen = panel.style.display=="block";
	if(config.options.chkAnimate)
		anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));
	else
		panel.style.display = isOpen ? "none" : "block" ;
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();
	return(false);
}
//}}}

// // Create control panel: HTML, CSS
//{{{
function createImportPanel(place) {
	var cmi=config.macros.importTiddlers; // abbreviation
	var panel=document.getElementById("importPanel");
	if (panel) { panel.parentNode.removeChild(panel); }
	setStylesheet(cmi.css,"importTiddlers");
	panel=createTiddlyElement(place,"span","importPanel",null,null)
	panel.innerHTML=cmi.html;
	refreshImportList();
	var siteURL=store.getTiddlerText("SiteUrl"); if (!siteURL) siteURL="";
	document.getElementById("importSourceURL").value=siteURL;
	cmi.src=siteURL;
	var siteProxy=store.getTiddlerText("SiteProxy"); if (!siteProxy) siteProxy="SiteProxy";
	document.getElementById("importSiteProxy").value=siteProxy;
	cmi.proxy=siteProxy;
	if (config.browser.isGecko) { // FF3 FIXUP
		document.getElementById("fileImportSource").style.display="none";
		document.getElementById("importLocalPanelFix").style.display="block";
	}
	return panel;
}
//}}}

// // CSS
//{{{
config.macros.importTiddlers.css = '\
#importPanel {\
	display: none; position:absolute; z-index:11; width:45em; right:105%; top:3em;\
	background-color: #eee; color:#000; font-size: 10pt; line-height:110%;\
	border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\
	padding: 0.5em; margin:0em; -moz-border-radius:1em;\
}\
#importPanel a, #importPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\
#importPanel table { width:100%; border:0px; padding:0px; margin:0px; font-size:10pt; line-height:110%; background:transparent; }\
#importPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\
#importPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\
#importPanel select { width:100%;margin:0px;font-size:10pt;line-height:110%;}\
#importPanel input  { width:98%;padding:0px;margin:0px;font-size:10pt;line-height:110%}\
#importPanel .box { border:1px solid #000; background-color:#eee; padding:3px 5px; margin-bottom:5px; -moz-border-radius:5px;}\
#importPanel .topline { border-top:1px solid #999; padding-top:2px; margin-top:2px; }\
#importPanel .rad { width:auto; }\
#importPanel .chk { width:auto; margin:1px;border:0; }\
#importPanel .btn { width:auto; }\
#importPanel .btn1 { width:98%; }\
#importPanel .btn2 { width:48%; }\
#importPanel .btn3 { width:32%; }\
#importPanel .btn4 { width:23%; }\
#importPanel .btn5 { width:19%; }\
#importPanel .importButton { padding: 0em; margin: 0px; font-size:10pt; }\
#importPanel .importListButton { padding:0em 0.25em 0em 0.25em; color: #000000; display:inline }\
#backstagePanel #importPanel { left:10%; right:auto; }\
';
//}}}

// // HTML 
//{{{
config.macros.importTiddlers.html = '\
<!-- source and report -->\
<table><tr><td align=left>\
	import from\
	<input type="radio" class="rad" name="importFrom" id="importFromFile" value="file" CHECKED\
		onclick="onClickImportButton(this,event)" title="show file controls"> local file\
	<input type="radio" class="rad" name="importFrom" id="importFromWeb"  value="http"\
		onclick="onClickImportButton(this,event)" title="show web controls"> web server\
</td><td align=right>\
	<input type=checkbox class="chk" id="chkImportReport" checked\
		onClick="config.options[\'chkImportReport\']=this.checked;"> create report\
</td></tr></table>\
\
<div class="box" id="importSourcePanel" style="margin:.5em">\
<div id="importLocalPanel" style="display:block;margin-bottom:2px;"><!-- import from local file  -->\
enter or browse for source path/filename<br>\
<input type="file" id="fileImportSource" size=57 style="width:100%"\
	onKeyUp="config.macros.importTiddlers.src=this.value"\
	onChange="config.macros.importTiddlers.src=this.value;document.getElementById(\'importLoad\').onclick()">\
<div id="importLocalPanelFix" style="display:none"><!-- FF3 FIXUP -->\
	<input type="text" id="fileImportSourceFix" style="width:90%"\
		title="Enter a path/file to import"\
		onKeyUp="config.macros.importTiddlers.src=this.value"\
		onChange="config.macros.importTiddlers.src=this.value; document.getElementById(\'importLoad\').onclick()">\
	<input type="button" id="fileImportSourceFixButton" style="width:7%" value="..."\
		title="Select a path/file to import"\
		onClick="var r=config.macros.importTiddlers.askForFilename(this); if (!r||!r.length) return;\
			document.getElementById(\'fileImportSourceFix\').value=r;\
			config.macros.importTiddlers.src=r;\
			document.getElementById(\'importLoad\').onclick()">\
</div><!--end FF3 FIXUP-->\
</div><!--end local-->\
<div id="importHTTPPanel" style="display:none;margin-bottom:2px;"><!-- import from http server -->\
<table><tr><td align=left>\
	enter a URL or <a href="javascript:;" id="importSelectFeed"\
		onclick="onClickImportButton(this,event)" title="select a pre-defined \'systemServer\' URL">\
		select a server</a><br>\
</td><td align=right>\
	<input type="checkbox" class="chk" id="importUsePassword"\
		onClick="config.macros.importTiddlers.usePassword=this.checked;\
			config.macros.importTiddlers.showPanel(\'importIDPWPanel\',this.checked,true);">password\
	<input type="checkbox" class="chk" id="importUseProxy"\
		onClick="config.macros.importTiddlers.useProxy=this.checked;\
			config.macros.importTiddlers.showPanel(\'importSiteProxy\',this.checked,true);">proxy\
</td></tr></table>\
<input type="text" id="importSiteProxy" style="display:none;margin-bottom:1px" onfocus="this.select()" value="SiteProxy"\
	onKeyUp="config.macros.importTiddlers.proxy=this.value"\
	onChange="config.macros.importTiddlers.proxy=this.value;">\
<input type="text" id="importSourceURL" onfocus="this.select()" value="SiteUrl"\
	onKeyUp="config.macros.importTiddlers.src=this.value"\
	onChange="config.macros.importTiddlers.src=this.value;">\
<div id="importIDPWPanel" style="text-align:center;margin-top:2px;display:none";>\
username: <input type=text id="txtImportID" style="width:25%" \
	onChange="config.options.txtRemoteUsername=this.value;">\
 password: <input type=password id="txtImportPW" style="width:25%" \
	onChange="config.options.txtRemotePassword=this.value;">\
</div><!--end idpw-->\
</div><!--end http-->\
</div><!--end source-->\
\
<div class="box" id="importSelectPanel" style="display:none;margin:.5em;">\
<table><tr><td align=left>\
select:\
<a href="javascript:;" id="importSelectAll"\
	onclick="onClickImportButton(this);return false;" title="SELECT all tiddlers">\
	all</a>\
&nbsp;<a href="javascript:;" id="importSelectNew"\
	onclick="onClickImportButton(this);return false;" title="SELECT tiddlers not already in destination document">\
	added</a>\
&nbsp;<a href="javascript:;" id="importSelectChanges"\
	onclick="onClickImportButton(this);return false;" title="SELECT tiddlers that have been updated in source document">\
	changes</a>\
&nbsp;<a href="javascript:;" id="importSelectDifferences"\
	onclick="onClickImportButton(this);return false;" title="SELECT tiddlers that have been added or are different from existing tiddlers">\
	differences</a>\
</td><td align=right>\
<a href="javascript:;" id="importListSmaller"\
	onclick="onClickImportButton(this);return false;" title="SHRINK list size">\
	&nbsp;&#150;&nbsp;</a>\
<a href="javascript:;" id="importListLarger"\
	onclick="onClickImportButton(this);return false;" title="GROW list size">\
	&nbsp;+&nbsp;</a>\
<a href="javascript:;" id="importListMaximize"\
	onclick="onClickImportButton(this);return false;" title="MAXIMIZE/RESTORE list size">\
	&nbsp;=&nbsp;</a>\
</td></tr></table>\
<select id="importList" size=20 multiple\
	onchange="setTimeout(\'refreshImportList(\'+this.selectedIndex+\')\',1)">\
	<!-- NOTE: delay refresh so list is updated AFTER onchange event is handled -->\
</select>\
<div style="text-align:center">\
	<a href="javascript:;"\
		title="click for help using filters..."\
		onclick="alert(\'A filter consists of one or more space-separated combinations of:\\n\\ntiddler titles\\ntag:[[tagvalue]]\\ntag:[[tag expression]] (requires MatchTagsPlugin)\\nstory:[[TiddlerName]]\\nsearch:[[searchtext]]\\n\\nUse a blank filter for all tiddlers.\')"\
	>filter</a>\
	<input type="text" id="importLastFilter" style="margin-bottom:1px; width:65%"\
		title="Enter a combination of one or more filters. Use a blank filter for all tiddlers."\
		onfocus="this.select()" value=""\
		onKeyUp="config.macros.importTiddlers.lastFilter=this.value"\
		onChange="config.macros.importTiddlers.lastFilter=this.value;">\
	<input type="button" id="importApplyFilter" style="width:20%" value="apply"\
		title="filter list of tiddlers to include only those that match certain criteria"\
		onclick="onClickImportButton(this)">\
	</div>\
</div><!--end select-->\
\
<div class="box" id="importOptionsPanel" style="text-align:center;margin:.5em;display:none;">\
	apply tags: <input type=checkbox class="chk" id="chkImportTags" checked\
		onClick="config.macros.importTiddlers.importTags=this.checked;">from source&nbsp;\
	<input type=checkbox class="chk" id="chkKeepTags" checked\
		onClick="config.macros.importTiddlers.keepTags=this.checked;">keep existing&nbsp;\
	<input type=checkbox class="chk" id="chkAddTags" \
		onClick="config.macros.importTiddlers.addTags=this.checked;\
			config.macros.importTiddlers.showPanel(\'txtNewTags\',this.checked,true);\
			if (this.checked) document.getElementById(\'txtNewTags\').focus();">add tags<br>\
	<input type=text id="txtNewTags" style="margin-top:4px;display:none;" size=15\ onfocus="this.select()" \
		title="enter tags to be added to imported tiddlers" \
		onKeyUp="config.macros.importTiddlers.newTags=this.value;\
		document.getElementById(\'chkAddTags\').checked=this.value.length>0;" autocomplete=off>\
	<nobr><input type=checkbox class="chk" id="chkSync" \
		onClick="config.macros.importTiddlers.sync=this.checked;">\
		link imported tiddlers to source document (for sync later)</nobr>\
</div><!--end options-->\
\
<div id="importButtonPanel" style="text-align:center">\
	<input type=button id="importLoad"	class="importButton btn3" value="open"\
		title="load listbox with tiddlers from source document"\
		onclick="onClickImportButton(this)">\
	<input type=button id="importOptions"	class="importButton btn3" value="options..."\
		title="set options for tags, sync, etc."\
		onclick="onClickImportButton(this)">\
	<input type=button id="importStart"	class="importButton btn3" value="import"\
		title="start/stop import of selected source tiddlers into current document"\
		onclick="onClickImportButton(this)">\
	<input type=button id="importClose"	class="importButton btn3" value="done"\
		title="clear listbox or hide control panel"\
		onclick="onClickImportButton(this)">\
</div>\
\
<div class="none" id="importCollisionPanel" style="display:none;margin:.5em 0 .5em .5em;">\
	<table><tr><td style="width:65%" align="left">\
		<table><tr><td align=left>\
			tiddler already exists:\
		</td><td align=right>\
			<input type=checkbox class="chk" id="importApplyToAll" \
			onclick="document.getElementById(\'importRename\').disabled=this.checked;"\
			checked>apply to all\
		</td></tr></table>\
		<input type=text id="importNewTitle" size=15 autocomplete=off">\
	</td><td style="width:34%" align="center">\
		<input type=button id="importMerge"\
			class="importButton" style="width:47%" value="merge"\
			title="append the incoming tiddler to the existing tiddler"\
			onclick="onClickImportButton(this)"><!--\
		--><input type=button id="importSkip"\
			class="importButton" style="width:47%" value="skip"\
			title="do not import this tiddler"\
			onclick="onClickImportButton(this)"><!--\
		--><br><input type=button id="importRename"\
			class="importButton" style="width:47%" value="rename"\
			title="rename the incoming tiddler"\
			onclick="onClickImportButton(this)"><!--\
		--><input type=button id="importReplace"\
			class="importButton" style="width:47%" value="replace"\
			title="discard the existing tiddler"\
			onclick="onClickImportButton(this)">\
	</td></tr></table>\
</div><!--end collision-->\
';
//}}}

// // Control interactions
//{{{
function onClickImportButton(which,event)
{
	var cmi=config.macros.importTiddlers; // abbreviation

	var list = document.getElementById('importList');
	if (!list) return;
	var thePanel = document.getElementById('importPanel');
	var theCollisionPanel = document.getElementById('importCollisionPanel');
	var theNewTitle = document.getElementById('importNewTitle');
	var count=0;
	switch (which.id)
		{
		case 'importFromFile':	// show local panel
		case 'importFromWeb':	// show HTTP panel
			cmi.local=(which.id=='importFromFile');
			cmi.showPanel('importLocalPanel',cmi.local);
			cmi.showPanel('importHTTPPanel',!cmi.local);
			break;
		case 'importOptions':	// show/hide options panel
			cmi.showPanel('importOptionsPanel',document.getElementById('importOptionsPanel').style.display=='none');
			break;
		case 'fileImportSource':
		case 'importLoad':		// load import source into hidden frame
			importReport();		// if an import was in progress, generate a report
			cmi.inbound=null;	// clear the imported tiddler buffer
			refreshImportList();	// reset/resize the listbox
			if (cmi.src=="") break;
			// Load document, read it's DOM and fill the list
			cmi.loadRemoteFile(cmi.src,cmi.filterTiddlerList);
			break;
		case 'importSelectFeed':	// select a pre-defined systemServer feed URL
			var p=Popup.create(which); if (!p) return;
			var tids=store.getTaggedTiddlers('systemServer');
			if (!tids.length)
				createTiddlyText(createTiddlyElement(p,'li'),'no pre-defined server feeds');
			for (var t=0; t<tids.length; t++) {
				var u=store.getTiddlerSlice(tids[t].title,"URL");
				var d=store.getTiddlerSlice(tids[t].title,"Description");
				if (!d||!d.length) d=store.getTiddlerSlice(tids[t].title,"description");
				if (!d||!d.length) d=u;
				createTiddlyButton(createTiddlyElement(p,'li'),tids[t].title,d,
					function(){
						var u=this.getAttribute('url');
						document.getElementById('importSourceURL').value=u;
						config.macros.importTiddlers.src=u;
						document.getElementById('importLoad').onclick();
					},
					null,null,null,{url:u});
			}
			Popup.show(p,false);
			event.cancelBubble = true;
			if (event.stopPropagation) event.stopPropagation();
			return(false);
			// create popup with feed list
			// onselect, insert feed URL into input field.
			break;
		case 'importSelectAll':		// select all tiddler list items (i.e., not headings)
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				if (list.options[t].value=="") continue;
				list.options[t].selected=true;
				count++;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			document.getElementById('importStart').disabled=!count;
			break;
		case 'importSelectNew':		// select tiddlers not in current document
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				list.options[t].selected=false;
				if (list.options[t].value=="") continue;
				list.options[t].selected=!store.tiddlerExists(list.options[t].value);
				count+=list.options[t].selected?1:0;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			document.getElementById('importStart').disabled=!count;
			break;
		case 'importSelectChanges':		// select tiddlers that are updated from existing tiddlers
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				list.options[t].selected=false;
				if (list.options[t].value==""||!store.tiddlerExists(list.options[t].value)) continue;
				for (var i=0; i<cmi.inbound.length; i++) // find matching inbound tiddler
					{ var inbound=cmi.inbound[i]; if (inbound.title==list.options[t].value) break; }
				list.options[t].selected=(inbound.modified-store.getTiddler(list.options[t].value).modified>0); // updated tiddler
				count+=list.options[t].selected?1:0;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			document.getElementById('importStart').disabled=!count;
			break;
		case 'importSelectDifferences':		// select tiddlers that are new or different from existing tiddlers
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				list.options[t].selected=false;
				if (list.options[t].value=="") continue;
				if (!store.tiddlerExists(list.options[t].value)) { list.options[t].selected=true; count++; continue; }
				for (var i=0; i<cmi.inbound.length; i++) // find matching inbound tiddler
					{ var inbound=cmi.inbound[i]; if (inbound.title==list.options[t].value) break; }
				list.options[t].selected=(inbound.modified-store.getTiddler(list.options[t].value).modified!=0); // changed tiddler
				count+=list.options[t].selected?1:0;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			document.getElementById('importStart').disabled=!count;
			break;
		case 'importApplyFilter':	// filter list to include only matching tiddlers
			importReport();		// if an import was in progress, generate a report
			clearMessage();
			if (!cmi.all) // no tiddlers loaded = "0 selected"
				{ displayMessage(cmi.countMsg.format([0])); return false; }
			var hash=document.getElementById('importLastFilter').value;
			cmi.inbound=cmi.filterByHash("#"+hash,cmi.all);
			refreshImportList();	// reset/resize the listbox
			break;
		case 'importStart':		// initiate the import processing
			importReport();		// if an import was in progress, generate a report
			document.getElementById('importApplyToAll').checked=false;
			document.getElementById('importStart').value=cmi.stopText;
			if (cmi.index>0) cmi.index=-1; // stop processing
			else cmi.index=importTiddlers(0); // or begin processing
			importStopped();
			break;
		case 'importClose':		// unload imported tiddlers or hide the import control panel
			// if imported tiddlers not loaded, close the import control panel
			if (!cmi.inbound) { thePanel.style.display='none'; break; }
			importReport();		// if an import was in progress, generate a report
			cmi.inbound=null;	// clear the imported tiddler buffer
			refreshImportList();	// reset/resize the listbox
			break;
		case 'importSkip':	// don't import the tiddler
			cmi.lastAction=which;
			var theItem	= list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported = cmi.inbound[j];
			theImported.status='skipped after asking';			// mark item as skipped
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index+1);	// resume with NEXT item
			importStopped();
			break;
		case 'importRename':		// change name of imported tiddler
			cmi.lastAction=which;
			var theItem		= list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported		= cmi.inbound[j];
			theImported.status	= 'renamed from '+theImported.title;	// mark item as renamed
			theImported.set(theNewTitle.value,null,null,null,null);		// change the tiddler title
			theItem.value		= theNewTitle.value;			// change the listbox item text
			theItem.text		= theNewTitle.value;			// change the listbox item text
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index);	// resume with THIS item
			importStopped();
			break;
		case 'importMerge':	// join existing and imported tiddler content
			cmi.lastAction=which;
			var theItem	= list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported	= cmi.inbound[j];
			var theExisting	= store.getTiddler(theItem.value);
			var theText	= theExisting.text+'\n----\n^^merged from: ';
			theText		+='[['+cmi.src+'#'+theItem.value+'|'+cmi.src+'#'+theItem.value+']]^^\n';
			theText		+='^^'+theImported.modified.toLocaleString()+' by '+theImported.modifier+'^^\n'+theImported.text;
			var theDate	= new Date();
			var theTags	= theExisting.getTags()+' '+theImported.getTags();
			theImported.set(null,theText,null,theDate,theTags);
			theImported.status   = 'merged with '+theExisting.title;	// mark item as merged
			theImported.status  += ' - '+theExisting.modified.formatString("MM/DD/YYYY 0hh:0mm:0ss");
			theImported.status  += ' by '+theExisting.modifier;
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index);	// resume with this item
			importStopped();
			break;
		case 'importReplace':		// substitute imported tiddler for existing tiddler
			cmi.lastAction=which;
			var theItem		  = list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported     = cmi.inbound[j];
			var theExisting	  = store.getTiddler(theItem.value);
			theImported.status  = 'replaces '+theExisting.title;		// mark item for replace
			theImported.status += ' - '+theExisting.modified.formatString("MM/DD/YYYY 0hh:0mm:0ss");
			theImported.status += ' by '+theExisting.modifier;
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index);	// resume with THIS item
			importStopped();
			break;
		case 'importListSmaller':		// decrease current listbox size, minimum=5
			if (list.options.length==1) break;
			list.size-=(list.size>5)?1:0;
			cmi.listsize=list.size;
			break;
		case 'importListLarger':		// increase current listbox size, maximum=number of items in list
			if (list.options.length==1) break;
			list.size+=(list.size<list.options.length)?1:0;
			cmi.listsize=list.size;
			break;
		case 'importListMaximize':	// toggle listbox size between current and maximum
			if (list.options.length==1) break;
			list.size=(list.size==list.options.length)?cmi.listsize:list.options.length;
			break;
		}
}
//}}}

// // toggle panel
//{{{
config.macros.importTiddlers.showPanel=function(place,show,skipAnim) {
	if (typeof place == "string") var place=document.getElementById(place);
	if (!place||!place.style) return;
	if(!skipAnim && anim && config.options.chkAnimate) anim.startAnimating(new Slider(place,show,false,"none"));
	else place.style.display=show?"block":"none";
}
//}}}

// // refresh listbox
//{{{
function refreshImportList(selectedIndex)
{
	var cmi=config.macros.importTiddlers; // abbreviation

	var list  = document.getElementById("importList");
	if (!list) return;
	// if nothing to show, reset list content and size
	if (!cmi.inbound) 
	{
		while (list.length > 0) { list.options[0] = null; }
		list.options[0]=new Option(cmi.loadText,"",false,false);
		list.size=cmi.listsize;

		// toggle buttons and panels
		document.getElementById('importLoad').disabled=false;
		document.getElementById('importLoad').style.display='inline';
		document.getElementById('importStart').disabled=true;
		document.getElementById('importOptions').disabled=true;
		document.getElementById('importOptions').style.display='none';
		document.getElementById('fileImportSource').disabled=false;
		document.getElementById('importFromFile').disabled=false;
		document.getElementById('importFromWeb').disabled=false;
		document.getElementById('importStart').value=cmi.startText;
		document.getElementById('importClose').value=cmi.doneText;
		document.getElementById('importSelectPanel').style.display='none';
		document.getElementById('importOptionsPanel').style.display='none';
		return;
	}
	// there are inbound tiddlers loaded...
	// toggle buttons and panels
	document.getElementById('importLoad').disabled=true;
	document.getElementById('importLoad').style.display='none';
	document.getElementById('importOptions').style.display='inline';
	document.getElementById('importOptions').disabled=false;
	document.getElementById('fileImportSource').disabled=true;
	document.getElementById('importFromFile').disabled=true;
	document.getElementById('importFromWeb').disabled=true;
	document.getElementById('importClose').value=cmi.closeText;
	if (document.getElementById('importSelectPanel').style.display=='none')
		cmi.showPanel('importSelectPanel',true);

	// get the sort order
	if (!selectedIndex)   selectedIndex=0;
	if (selectedIndex==0) cmi.sort='title';		// heading
	if (selectedIndex==1) cmi.sort='title';
	if (selectedIndex==2) cmi.sort='modified';
	if (selectedIndex==3) cmi.sort='tags';
	if (selectedIndex>3) {
		// display selected tiddler count
		for (var t=0,count=0; t < list.options.length; t++) {
			if (!list.options[t].selected) continue;
			if (list.options[t].value!="")
				count+=1;
			else { // if heading is selected, deselect it, and then select and count all in section
				list.options[t].selected=false;
				for ( t++; t<list.options.length && list.options[t].value!=""; t++) {
					list.options[t].selected=true;
					count++;
				}
			}
		}
		clearMessage(); displayMessage(cmi.countMsg.format([count]));
	}
	document.getElementById('importStart').disabled=!count;
	if (selectedIndex>3) return; // no refresh needed

	// get the alphasorted list of tiddlers
	var tiddlers=cmi.inbound;
	tiddlers.sort(function (a,b) {if(a['title'] == b['title']) return(0); else return (a['title'] < b['title']) ? -1 : +1; });
	// clear current list contents
	while (list.length > 0) { list.options[0] = null; }
	// add heading and control items to list
	var i=0;
	var indent=String.fromCharCode(160)+String.fromCharCode(160);
	if (cmi.all.length==tiddlers.length)
		var summary=cmi.summaryMsg.format([tiddlers.length,(tiddlers.length!=1)?cmi.plural:cmi.single]);
	else
		var summary=cmi.summaryFilteredMsg.format([tiddlers.length,cmi.all.length,(cmi.all.length!=1)?cmi.plural:cmi.single]);
	list.options[i++]=new Option(summary,"",false,false);
	list.options[i++]=new Option(((cmi.sort=="title"   )?">":indent)+' [by title]',"",false,false);
	list.options[i++]=new Option(((cmi.sort=="modified")?">":indent)+' [by date]',"",false,false);
	list.options[i++]=new Option(((cmi.sort=="tags")?">":indent)+' [by tags]',"",false,false);
	// output the tiddler list
	switch(cmi.sort) {
		case "title":
			for(var t = 0; t < tiddlers.length; t++)
				list.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);
			break;
		case "modified":
			// sort descending for newest date first
			tiddlers.sort(function (a,b) {if(a['modified'] == b['modified']) return(0); else return (a['modified'] > b['modified']) ? -1 : +1; });
			var lastSection = "";
			for(var t = 0; t < tiddlers.length; t++) {
				var tiddler = tiddlers[t];
				var theSection = tiddler.modified.toLocaleDateString();
				if (theSection != lastSection) {
					list.options[i++] = new Option(theSection,"",false,false);
					lastSection = theSection;
				}
				list.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);
			}
			break;
		case "tags":
			var theTitles = {}; // all tiddler titles, hash indexed by tag value
			var theTags = new Array();
			for(var t=0; t<tiddlers.length; t++) {
				var title=tiddlers[t].title;
				var tags=tiddlers[t].tags;
				if (!tags || !tags.length) {
					if (theTitles["untagged"]==undefined) { theTags.push("untagged"); theTitles["untagged"]=new Array(); }
					theTitles["untagged"].push(title);
				}
				else for(var s=0; s<tags.length; s++) {
					if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }
					theTitles[tags[s]].push(title);
				}
			}
			theTags.sort();
			for(var tagindex=0; tagindex<theTags.length; tagindex++) {
				var theTag=theTags[tagindex];
				list.options[i++]=new Option(theTag,"",false,false);
				for(var t=0; t<theTitles[theTag].length; t++)
					list.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);
			}
			break;
		}
	list.selectedIndex=selectedIndex;		  // select current control item
	if (list.size<cmi.listsize) list.size=cmi.listsize;
	if (list.size>list.options.length) list.size=list.options.length;
}

config.macros.importTiddlers.filterTiddlerList=function(success,params,txt,src,xhr) {
	var cmi=config.macros.importTiddlers; // abbreviation
	var src=src.replace(/%20/g," ");
	if (!success) { displayMessage(cmi.openErrMsg.format([src,xhr.status])); return; }
	cmi.all = cmi.readTiddlersFromHTML(txt);
	var count=cmi.all?cmi.all.length:0;
	var querypos=src.lastIndexOf("?"); if (querypos!=-1) src=src.substr(0,querypos);
	displayMessage(cmi.foundMsg.format([count,src]));
	cmi.inbound=cmi.filterByHash(params,cmi.all); // use full URL including hash (if any)
	document.getElementById("importLastFilter").value=cmi.lastFilter;
	window.refreshImportList(0);
}

config.macros.importTiddlers.filterByHash=function(src,tiddlers)
{
	var hashpos=src.lastIndexOf("#"); if (hashpos==-1) return tiddlers;
	var hash=src.substr(hashpos+1); if (!hash.length) return tiddlers;
	var tids=[];
	var params=hash.parseParams("anon",null,true,false,false);
	for (var p=1; p<params.length; p++) {
		switch (params[p].name) {
			case "anon":
			case "open":
				tids.pushUnique(params[p].value);
				break;
			case "tag":
				if (store.getMatchingTiddlers) { // for boolean expressions - see MatchTagsPlugin
					var r=store.getMatchingTiddlers(params[p].value,null,tiddlers);
					for (var t=0; t<r.length; t++) tids.pushUnique(r[t].title);
				} else for (var t=0; t<tiddlers.length; t++)
					if (tiddlers[t].isTagged(params[p].value))
						tids.pushUnique(tiddlers[t].title);
				break;
			case "story":
				for (var t=0; t<tiddlers.length; t++)
					if (tiddlers[t].title==params[p].value) {
						tiddlers[t].changed();
						for (var s=0; s<tiddlers[t].links.length; s++)
							tids.pushUnique(tiddlers[t].links[s]);
						break;
					}
				break;
			case "search":
				for (var t=0; t<tiddlers.length; t++)
					if (tiddlers[t].text.indexOf(params[p].value)!=-1)
						tids.pushUnique(tiddlers[t].title);
				break;
		}
	}
	var matches=[];
	for (var t=0; t<tiddlers.length; t++)
		if (tids.contains(tiddlers[t].title))
			matches.push(tiddlers[t]);
	displayMessage(config.macros.importTiddlers.filterMsg.format([matches.length,hash]));
	config.macros.importTiddlers.lastFilter=hash;
	return matches;
}
//}}}

// // re-entrant processing for handling import with interactive collision prompting
//{{{
function importTiddlers(startIndex)
{
	var cmi=config.macros.importTiddlers; // abbreviation

	if (!cmi.inbound) return -1;

	var list = document.getElementById('importList');
	if (!list) return;
	var t;
	// if starting new import, reset import status flags
	if (startIndex==0)
		for (var t=0;t<cmi.inbound.length;t++)
			cmi.inbound[t].status="";
	for (var i=startIndex; i<list.options.length; i++)
		{
		// if list item is not selected or is a heading (i.e., has no value), skip it
		if ((!list.options[i].selected) || ((t=list.options[i].value)==""))
			continue;
		for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==t) break;
		var inbound = cmi.inbound[j];
		var theExisting = store.getTiddler(inbound.title);
		// avoid redundant import for tiddlers that are listed multiple times (when 'by tags')
		if (inbound.status=="added")
			continue;
		// don't import the "ImportedTiddlers" history from the other document...
		if (inbound.title=='ImportedTiddlers')
			continue;
		// if tiddler exists and import not marked for replace or merge, stop importing
		if (theExisting && (inbound.status.substr(0,7)!="replace") && (inbound.status.substr(0,5)!="merge"))
			return i;
		// assemble tags (remote + existing + added)
		var newTags = "";
		if (cmi.importTags)
			newTags+=inbound.getTags()	// import remote tags
		if (cmi.keepTags && theExisting)
			newTags+=" "+theExisting.getTags(); // keep existing tags
		if (cmi.addTags && cmi.newTags.trim().length)
			newTags+=" "+cmi.newTags; // add new tags
		inbound.set(null,null,null,null,newTags.trim());
		// set the status to 'added' (if not already set by the 'ask the user' UI)
		inbound.status=(inbound.status=="")?'added':inbound.status;
		// set sync fields
		if (cmi.sync) {
			if (!inbound.fields) inbound.fields={}; // for TW2.1.x backward-compatibility
			inbound.fields["server.page.revision"]=inbound.modified.convertToYYYYMMDDHHMM();
			inbound.fields["server.type"]="file";
			inbound.fields["server.host"]=(cmi.local?"file://":"")+cmi.src;
		}
		// do the import!
		store.suspendNotifications();
		store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, inbound.tags, inbound.fields, true, inbound.created);
                store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value (needed for TW2.1.x and earlier)
		store.resumeNotifications();
		}
	return(-1);	// signals that we really finished the entire list
}
//}}}

//{{{
function importStopped()
{
	var cmi=config.macros.importTiddlers; // abbreviation
	var list = document.getElementById('importList');
	var theNewTitle = document.getElementById('importNewTitle');
	if (!list) return;
	if (cmi.index==-1){ 
		document.getElementById('importStart').value=cmi.startText;
		importReport();		// import finished... generate the report
	} else {
		// import collision...
		// show the collision panel and set the title edit field
		document.getElementById('importStart').value=cmi.stopText;
		cmi.showPanel('importCollisionPanel',true);
		theNewTitle.value=list.options[cmi.index].value;
		if (document.getElementById('importApplyToAll').checked
			&& cmi.lastAction
			&& cmi.lastAction.id!="importRename") {
			onClickImportButton(cmi.lastAction);
		}
	}
}
//}}}

// // ''REPORT GENERATOR''
//{{{
function importReport()
{
	var cmi=config.macros.importTiddlers; // abbreviation
	if (!cmi.inbound) return;

	// if import was not completed, the collision panel will still be open... close it now.
	var panel=document.getElementById('importCollisionPanel'); if (panel) panel.style.display='none';

	// get the alphasorted list of tiddlers
	var tiddlers = cmi.inbound;
	// gather the statistics
	var count=0; var total=0;
	for (var t=0; t<tiddlers.length; t++) {
		if (!tiddlers[t].status || !tiddlers[t].status.trim().length) continue;
		if (tiddlers[t].status.substr(0,7)!="skipped") count++;
		total++;
	}
	// generate a report
	if (total) displayMessage(cmi.processedMsg.format([total]));
	if (count && config.options.chkImportReport) {
		// get/create the report tiddler
		var theReport = store.getTiddler('ImportedTiddlers');
		if (!theReport) { theReport= new Tiddler(); theReport.title = 'ImportedTiddlers'; theReport.text  = ""; }
		// format the report content
		var now = new Date();
		var newText = "On "+now.toLocaleString()+", "+config.options.txtUserName
		newText +=" imported "+count+" tiddler"+(count==1?"":"s")+" from\n[["+cmi.src+"|"+cmi.src+"]]:\n";
		if (cmi.addTags && cmi.newTags.trim().length)
			newText += "imported tiddlers were tagged with: \""+cmi.newTags+"\"\n";
		newText += "<<<\n";
		for (var t=0; t<tiddlers.length; t++) if (tiddlers[t].status) newText += "#[["+tiddlers[t].title+"]] - "+tiddlers[t].status+"\n";
		newText += "<<<\n";
		// update the ImportedTiddlers content and show the tiddler
		theReport.text	 = newText+((theReport.text!="")?'\n----\n':"")+theReport.text;
		theReport.modifier = config.options.txtUserName;
		theReport.modified = new Date();
                store.saveTiddler(theReport.title, theReport.title, theReport.text, theReport.modifier, theReport.modified, theReport.tags, theReport.fields);
		story.displayTiddler(null,theReport.title,1,null,null,false);
		story.refreshTiddler(theReport.title,1,true);
	}

	// reset status flags
	for (var t=0; t<cmi.inbound.length; t++) cmi.inbound[t].status="";

	// mark document as dirty and let display update as needed
	if (count) { store.setDirty(true); store.notifyAll(); }

	// always show final message when tiddlers were actually loaded
	if (count) displayMessage(cmi.importedMsg.format([count,tiddlers.length,cmi.src.replace(/%20/g," ")]));
}
//}}}

// // File and XMLHttpRequest I/O
//{{{
config.macros.importTiddlers.askForFilename=function(here) {
	var msg=here.title; // use tooltip as dialog box message
	var path=getLocalPath(document.location.href);
	var slashpos=path.lastIndexOf("/"); if (slashpos==-1) slashpos=path.lastIndexOf("\\"); 
	if (slashpos!=-1) path = path.substr(0,slashpos+1); // remove filename from path, leave the trailing slash
	var file="";
	var result="";
	if(window.Components) { // moz
		try {
			netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
			var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
			var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
			picker.init(window, msg, nsIFilePicker.modeOpen);
			var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
			thispath.initWithPath(path);
			picker.displayDirectory=thispath;
			picker.defaultExtension='html';
			picker.defaultString=file;
			picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
			if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
		}
		catch(e) { alert('error during local file access: '+e.toString()) }
	}
	else { // IE
		try { // XPSP2 IE only
			var s = new ActiveXObject('UserAccounts.CommonDialog');
			s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';
			s.FilterIndex=3; // default to HTML files;
			s.InitialDir=path;
			s.FileName=file;
			if (s.showOpen()) var result=s.FileName;
		}
		catch(e) {  // fallback
			var result=prompt(msg,path+file);
		}
	}
	return result;
}

config.macros.importTiddlers.loadRemoteFile = function(src,callback) {
	if (src==undefined || !src.length) return null; // filename is required
	var original=src; // URL as specified
	var hashpos=src.indexOf("#"); if (hashpos!=-1) src=src.substr(0,hashpos); // URL with #... suffix removed (needed for IE)
	clearMessage();
	displayMessage(this.openMsg.format([src.replace(/%20/g," ")]));
	if (src.substr(0,5)!="http:" && src.substr(0,5)!="file:") { // if not a URL, read from local filesystem
		var txt=loadFile(src);
		if (!txt) { // file didn't load, might be relative path.. try fixup
			var pathPrefix=document.location.href;  // get current document path and trim off filename
			var slashpos=pathPrefix.lastIndexOf("/"); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf("\\"); 
			if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
			src=pathPrefix+src;
			if (pathPrefix.substr(0,5)!="http:") src=getLocalPath(src);
			var txt=loadFile(src);
		}
		if (!txt) { // file still didn't load, report error
			displayMessage(config.macros.importTiddlers.openErrMsg.format([src.replace(/%20/g," "),"(filesystem error)"]));
		} else {
			displayMessage(config.macros.importTiddlers.readMsg.format([txt.length,src.replace(/%20/g," ")]));
			if (callback) callback(true,original,convertUTF8ToUnicode(txt),src,null);
		}
	} else {
		var name=config.options.txtRemoteUsername; var pass=config.options.txtRemotePassword;
		var xhr=doHttp("GET",src,null,null,name,pass,callback,original,null)
		if (!xhr) displayMessage(config.macros.importTiddlers.openErrMsg.format([src,"(XMLHTTPRequest error)"]));
	}
}

config.macros.importTiddlers.readTiddlersFromHTML=function(html)
{
	var remoteStore=new TiddlyWiki();
	remoteStore.importTiddlyWiki(html);
	return remoteStore.getTiddlers("title");	
}
//}}}
/***
|''Name:''|IntelliTaggerPlugin|
|''Version:''|1.0.2 (2007-07-25)|
|''Type:''|plugin|
|''Source:''|http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin|
|''Author:''|Udo Borkowski (ub [at] abego-software [dot] de)|
|''Documentation:''|[[IntelliTaggerPlugin Documentation]]|
|''~SourceCode:''|[[IntelliTaggerPlugin SourceCode]]|
|''Licence:''|[[BSD open source license (abego Software)]]|
|''~CoreVersion:''|2.0.8|
|''Browser:''|Firefox 1.5.0.2 or better|
***/
/***
!Version History
* 1.0.2 (2007-07-25): 
** Feature: "Return" key may be used to accept first tag suggestion (beside "Alt-1")
** Bugfix: Keyboard shortcuts (Alt+3 etc.) shifted
* 1.0.1 (2007-05-18): Improvement: Speedup when using TiddlyWikis with many tags
* 1.0.0 (2006-04-26): Initial release

***/
// /%
if(!version.extensions.IntelliTaggerPlugin){if(!window.abego){window.abego={};}if(!abego.internal){abego.internal={};}abego.alertAndThrow=function(s){alert(s);throw s;};if(version.major<2){abego.alertAndThrow("Use TiddlyWiki 2.0.8 or better to run the IntelliTagger Plugin.");}version.extensions.IntelliTaggerPlugin={major:1,minor:0,revision:2,date:new Date(2007,6,25),type:"plugin",source:"http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin",documentation:"[[IntelliTaggerPlugin Documentation]]",sourcecode:"[[IntelliTaggerPlugin SourceCode]]",author:"Udo Borkowski (ub [at] abego-software [dot] de)",licence:"[[BSD open source license (abego Software)]]",tiddlywiki:"Version 2.0.8 or better",browser:"Firefox 1.5.0.2 or better"};abego.createEllipsis=function(_2){var e=createTiddlyElement(_2,"span");e.innerHTML="&hellip;";};abego.isPopupOpen=function(_4){return _4&&_4.parentNode==document.body;};abego.openAsPopup=function(_5){if(_5.parentNode!=document.body){document.body.appendChild(_5);}};abego.closePopup=function(_6){if(abego.isPopupOpen(_6)){document.body.removeChild(_6);}};abego.getWindowRect=function(){return {left:findScrollX(),top:findScrollY(),height:findWindowHeight(),width:findWindowWidth()};};abego.moveElement=function(_7,_8,_9){_7.style.left=_8+"px";_7.style.top=_9+"px";};abego.centerOnWindow=function(_a){if(_a.style.position!="absolute"){throw "abego.centerOnWindow: element must have absolute position";}var _b=abego.getWindowRect();abego.moveElement(_a,_b.left+(_b.width-_a.offsetWidth)/2,_b.top+(_b.height-_a.offsetHeight)/2);};abego.isDescendantOrSelf=function(_c,e){while(e){if(_c==e){return true;}e=e.parentNode;}return false;};abego.toSet=function(_e){var _f={};for(var i=0;i<_e.length;i++){_f[_e[i]]=true;}return _f;};abego.filterStrings=function(_11,_12,_13){var _14=[];for(var i=0;i<_11.length&&(_13===undefined||_14.length<_13);i++){var s=_11[i];if(s.match(_12)){_14.push(s);}}return _14;};abego.arraysAreEqual=function(a,b){if(!a){return !b;}if(!b){return false;}var n=a.length;if(n!=b.length){return false;}for(var i=0;i<n;i++){if(a[i]!=b[i]){return false;}}return true;};abego.moveBelowAndClip=function(_1b,_1c){if(!_1c){return;}var _1d=findPosX(_1c);var _1e=findPosY(_1c);var _1f=_1c.offsetHeight;var _20=_1d;var _21=_1e+_1f;var _22=findWindowWidth();if(_22<_1b.offsetWidth){_1b.style.width=(_22-100)+"px";}var _23=_1b.offsetWidth;if(_20+_23>_22){_20=_22-_23-30;}if(_20<0){_20=0;}_1b.style.left=_20+"px";_1b.style.top=_21+"px";_1b.style.display="block";};abego.compareStrings=function(a,b){return (a==b)?0:(a<b)?-1:1;};abego.sortIgnoreCase=function(arr){var _27=[];var n=arr.length;for(var i=0;i<n;i++){var s=arr[i];_27.push([s.toString().toLowerCase(),s]);}_27.sort(function(a,b){return (a[0]==b[0])?0:(a[0]<b[0])?-1:1;});for(i=0;i<n;i++){arr[i]=_27[i][1];}};abego.getTiddlerField=function(_2d,_2e,_2f){var _30=document.getElementById(_2d.idPrefix+_2e);var e=null;if(_30!=null){var _32=_30.getElementsByTagName("*");for(var t=0;t<_32.length;t++){var c=_32[t];if(c.tagName.toLowerCase()=="input"||c.tagName.toLowerCase()=="textarea"){if(!e){e=c;}if(c.getAttribute("edit")==_2f){e=c;}}}}return e;};abego.setRange=function(_35,_36,end){if(_35.setSelectionRange){_35.setSelectionRange(_36,end);var max=0+_35.scrollHeight;var len=_35.textLength;var top=max*_36/len,bot=max*end/len;_35.scrollTop=Math.min(top,(bot+top-_35.clientHeight)/2);}else{if(_35.createTextRange!=undefined){var _3b=_35.createTextRange();_3b.collapse();_3b.moveEnd("character",end);_3b.moveStart("character",_36);_3b.select();}else{_35.select();}}};abego.internal.TagManager=function(){var _3c=null;var _3d=function(){if(_3c){return;}_3c={};store.forEachTiddler(function(_3e,_3f){for(var i=0;i<_3f.tags.length;i++){var tag=_3f.tags[i];var _42=_3c[tag];if(!_42){_42=_3c[tag]={count:0,tiddlers:{}};}_42.tiddlers[_3f.title]=true;_42.count+=1;}});};var _43=TiddlyWiki.prototype.saveTiddler;TiddlyWiki.prototype.saveTiddler=function(_44,_45,_46,_47,_48,_49){var _4a=this.fetchTiddler(_44);var _4b=_4a?_4a.tags:[];var _4c=(typeof _49=="string")?_49.readBracketedList():_49;_43.apply(this,arguments);if(!abego.arraysAreEqual(_4b,_4c)){abego.internal.getTagManager().reset();}};var _4d=TiddlyWiki.prototype.removeTiddler;TiddlyWiki.prototype.removeTiddler=function(_4e){var _4f=this.fetchTiddler(_4e);var _50=_4f&&_4f.tags.length>0;_4d.apply(this,arguments);if(_50){abego.internal.getTagManager().reset();}};this.reset=function(){_3c=null;};this.getTiddlersWithTag=function(tag){_3d();var _52=_3c[tag];return _52?_52.tiddlers:null;};this.getAllTags=function(_53){_3d();var _54=[];for(var i in _3c){_54.push(i);}for(i=0;_53&&i<_53.length;i++){_54.pushUnique(_53[i],true);}abego.sortIgnoreCase(_54);return _54;};this.getTagInfos=function(){_3d();var _56=[];for(var _57 in _3c){_56.push([_57,_3c[_57]]);}return _56;};var _58=function(a,b){var a1=a[1];var b1=b[1];var d=b[1].count-a[1].count;return d!=0?d:abego.compareStrings(a[0].toLowerCase(),b[0].toLowerCase());};this.getSortedTagInfos=function(){_3d();var _5e=this.getTagInfos();_5e.sort(_58);return _5e;};this.getPartnerRankedTags=function(_5f){var _60={};for(var i=0;i<_5f.length;i++){var _62=this.getTiddlersWithTag(_5f[i]);for(var _63 in _62){var _64=store.getTiddler(_63);if(!(_64 instanceof Tiddler)){continue;}for(var j=0;j<_64.tags.length;j++){var tag=_64.tags[j];var c=_60[tag];_60[tag]=c?c+1:1;}}}var _68=abego.toSet(_5f);var _69=[];for(var n in _60){if(!_68[n]){_69.push(n);}}_69.sort(function(a,b){var d=_60[b]-_60[a];return d!=0?d:abego.compareStrings(a.toLowerCase(),b.toLowerCase());});return _69;};};abego.internal.getTagManager=function(){if(!abego.internal.gTagManager){abego.internal.gTagManager=new abego.internal.TagManager();}return abego.internal.gTagManager;};(function(){var _6e=2;var _6f=1;var _70=30;var _71;var _72;var _73;var _74;var _75;var _76;if(!abego.IntelliTagger){abego.IntelliTagger={};}var _77=function(){return _72;};var _78=function(tag){return _75[tag];};var _7a=function(s){var i=s.lastIndexOf(" ");return (i>=0)?s.substr(0,i):"";};var _7d=function(_7e){var s=_7e.value;var len=s.length;return (len>0&&s[len-1]!=" ");};var _81=function(_82){var s=_82.value;var len=s.length;if(len>0&&s[len-1]!=" "){_82.value+=" ";}};var _85=function(tag,_87,_88){if(_7d(_87)){_87.value=_7a(_87.value);}story.setTiddlerTag(_88.title,tag,0);_81(_87);abego.IntelliTagger.assistTagging(_87,_88);};var _89=function(n){if(_76&&_76.length>n){return _76[n];}return (_74&&_74.length>n)?_74[n]:null;};var _8b=function(n,_8d,_8e){var _8f=_89(n);if(_8f){_85(_8f,_8d,_8e);}};var _90=function(_91){var pos=_91.value.lastIndexOf(" ");var _93=(pos>=0)?_91.value.substr(++pos,_91.value.length):_91.value;return new RegExp(_93.escapeRegExp(),"i");};var _94=function(_95,_96){var _97=0;for(var i=0;i<_95.length;i++){if(_96[_95[i]]){_97++;}}return _97;};var _99=function(_9a,_9b,_9c){var _9d=1;var c=_9a[_9b];for(var i=_9b+1;i<_9a.length;i++){if(_9a[i][1].count==c){if(_9a[i][0].match(_9c)){_9d++;}}else{break;}}return _9d;};var _a0=function(_a1,_a2){var _a3=abego.internal.getTagManager().getSortedTagInfos();var _a4=[];var _a5=0;for(var i=0;i<_a3.length;i++){var c=_a3[i][1].count;if(c!=_a5){if(_a2&&(_a4.length+_99(_a3,i,_a1)>_a2)){break;}_a5=c;}if(c==1){break;}var s=_a3[i][0];if(s.match(_a1)){_a4.push(s);}}return _a4;};var _a9=function(_aa,_ab){return abego.filterStrings(abego.internal.getTagManager().getAllTags(_ab),_aa);};var _ac=function(){if(!_71){return;}var _ad=store.getTiddlerText("IntelliTaggerMainTemplate");if(!_ad){_ad="<b>Tiddler IntelliTaggerMainTemplate not found</b>";}_71.innerHTML=_ad;applyHtmlMacros(_71,null);refreshElements(_71,null);};var _ae=function(e){if(!e){var e=window.event;}var tag=this.getAttribute("tag");if(_73){_73.call(this,tag,e);}return false;};var _b2=function(_b3){createTiddlyElement(_b3,"span",null,"tagSeparator"," | ");};var _b4=function(_b5,_b6,_b7,_b8,_b9){if(!_b6){return;}var _ba=_b8?abego.toSet(_b8):{};var n=_b6.length;var c=0;for(var i=0;i<n;i++){var tag=_b6[i];if(_ba[tag]){continue;}if(c>0){_b2(_b5);}if(_b9&&c>=_b9){abego.createEllipsis(_b5);break;}c++;var _bf="";var _c0=_b5;if(_b7<10){_c0=createTiddlyElement(_b5,"span",null,"numberedSuggestion");_b7++;var key=_b7<10?""+(_b7):"0";createTiddlyElement(_c0,"span",null,"suggestionNumber",key+") ");var _c2=_b7==1?"Return or ":"";_bf=" (Shortcut: %1Alt-%0)".format([key,_c2]);}var _c3=config.views.wikified.tag.tooltip.format([tag]);var _c4=(_78(tag)?"Remove tag '%0'%1":"Add tag '%0'%1").format([tag,_bf]);var _c5="%0; Shift-Click: %1".format([_c4,_c3]);var btn=createTiddlyButton(_c0,tag,_c5,_ae,_78(tag)?"currentTag":null);btn.setAttribute("tag",tag);}};var _c7=function(){if(_71){window.scrollTo(0,ensureVisible(_71));}if(_77()){window.scrollTo(0,ensureVisible(_77()));}};var _c8=function(e){if(!e){var e=window.event;}if(!_71){return;}var _cb=resolveTarget(e);if(_cb==_77()){return;}if(abego.isDescendantOrSelf(_71,_cb)){return;}abego.IntelliTagger.close();};addEvent(document,"click",_c8);var _cc=Story.prototype.gatherSaveFields;Story.prototype.gatherSaveFields=function(e,_ce){_cc.apply(this,arguments);var _cf=_ce.tags;if(_cf){_ce.tags=_cf.trim();}};var _d0=function(_d1){story.focusTiddler(_d1,"tags");var _d2=abego.getTiddlerField(story,_d1,"tags");if(_d2){var len=_d2.value.length;abego.setRange(_d2,len,len);window.scrollTo(0,ensureVisible(_d2));}};var _d4=config.macros.edit.handler;config.macros.edit.handler=function(_d5,_d6,_d7,_d8,_d9,_da){_d4.apply(this,arguments);var _db=_d7[0];if((_da instanceof Tiddler)&&_db=="tags"){var _dc=_d5.lastChild;_dc.onfocus=function(e){abego.IntelliTagger.assistTagging(_dc,_da);setTimeout(function(){_d0(_da.title);},100);};_dc.onkeyup=function(e){if(!e){var e=window.event;}if(e.altKey&&!e.ctrlKey&&!e.metaKey&&(e.keyCode>=48&&e.keyCode<=57)){_8b(e.keyCode==48?9:e.keyCode-49,_dc,_da);}else{if(e.ctrlKey&&e.keyCode==32){_8b(0,_dc,_da);}}if(!e.ctrlKey&&(e.keyCode==13||e.keyCode==10)){_8b(0,_dc,_da);}setTimeout(function(){abego.IntelliTagger.assistTagging(_dc,_da);},100);return false;};_81(_dc);}};var _e0=function(e){if(!e){var e=window.event;}var _e3=resolveTarget(e);var _e4=_e3.getAttribute("tiddler");if(_e4){story.displayTiddler(_e3,_e4,"IntelliTaggerEditTagsTemplate",false);_d0(_e4);}return false;};var _e5=config.macros.tags.handler;config.macros.tags.handler=function(_e6,_e7,_e8,_e9,_ea,_eb){_e5.apply(this,arguments);abego.IntelliTagger.createEditTagsButton(_eb,createTiddlyElement(_e6.lastChild,"li"));};var _ec=function(){if(_71&&_72&&!abego.isDescendantOrSelf(document,_72)){abego.IntelliTagger.close();}};setInterval(_ec,100);abego.IntelliTagger.displayTagSuggestions=function(_ed,_ee,_ef,_f0,_f1){_74=_ed;_75=abego.toSet(_ee);_76=_ef;_72=_f0;_73=_f1;if(!_71){_71=createTiddlyElement(document.body,"div",null,"intelliTaggerSuggestions");_71.style.position="absolute";}_ac();abego.openAsPopup(_71);if(_77()){var w=_77().offsetWidth;if(_71.offsetWidth<w){_71.style.width=(w-2*(_6e+_6f))+"px";}abego.moveBelowAndClip(_71,_77());}else{abego.centerOnWindow(_71);}_c7();};abego.IntelliTagger.assistTagging=function(_f3,_f4){var _f5=_90(_f3);var s=_f3.value;if(_7d(_f3)){s=_7a(s);}var _f7=s.readBracketedList();var _f8=_f7.length>0?abego.filterStrings(abego.internal.getTagManager().getPartnerRankedTags(_f7),_f5,_70):_a0(_f5,_70);abego.IntelliTagger.displayTagSuggestions(_a9(_f5,_f7),_f7,_f8,_f3,function(tag,e){if(e.shiftKey){onClickTag.call(this,e);}else{_85(tag,_f3,_f4);}});};abego.IntelliTagger.close=function(){abego.closePopup(_71);_71=null;return false;};abego.IntelliTagger.createEditTagsButton=function(_fb,_fc,_fd,_fe,_ff,id,_101){if(!_fd){_fd="[edit]";}if(!_fe){_fe="Edit the tags";}if(!_ff){_ff="editTags";}var _102=createTiddlyButton(_fc,_fd,_fe,_e0,_ff,id,_101);_102.setAttribute("tiddler",(_fb instanceof Tiddler)?_fb.title:String(_fb));return _102;};abego.IntelliTagger.getSuggestionTagsMaxCount=function(){return 100;};config.macros.intelliTagger={label:"intelliTagger",handler:function(_103,_104,_105,_106,_107,_108){var _109=_107.parseParams("list",null,true);var _10a=_109[0]["action"];for(var i=0;_10a&&i<_10a.length;i++){var _10c=_10a[i];var _10d=config.macros.intelliTagger.subhandlers[_10c];if(!_10d){abego.alertAndThrow("Unsupported action '%0'".format([_10c]));}_10d(_103,_104,_105,_106,_107,_108);}},subhandlers:{showTags:function(_10e,_10f,_110,_111,_112,_113){_b4(_10e,_74,_76?_76.length:0,_76,abego.IntelliTagger.getSuggestionTagsMaxCount());},showFavorites:function(_114,_115,_116,_117,_118,_119){_b4(_114,_76,0);},closeButton:function(_11a,_11b,_11c,_11d,_11e,_11f){var _120=createTiddlyButton(_11a,"close","Close the suggestions",abego.IntelliTagger.close);},version:function(_121){var t="IntelliTagger %0.%1.%2".format([version.extensions.IntelliTaggerPlugin.major,version.extensions.IntelliTaggerPlugin.minor,version.extensions.IntelliTaggerPlugin.revision]);var e=createTiddlyElement(_121,"a");e.setAttribute("href","http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin");e.innerHTML="<font color=\"black\" face=\"Arial, Helvetica, sans-serif\">"+t+"<font>";},copyright:function(_124){var e=createTiddlyElement(_124,"a");e.setAttribute("href","http://tiddlywiki.abego-software.de");e.innerHTML="<font color=\"black\" face=\"Arial, Helvetica, sans-serif\">&copy; 2006-2007 <b><font color=\"red\">abego</font></b> Software<font>";}}};})();config.shadowTiddlers["IntelliTaggerStyleSheet"]="/***\n"+"!~IntelliTagger Stylesheet\n"+"***/\n"+"/*{{{*/\n"+".intelliTaggerSuggestions {\n"+"\tposition: absolute;\n"+"\twidth: 600px;\n"+"\n"+"\tpadding: 2px;\n"+"\tlist-style: none;\n"+"\tmargin: 0;\n"+"\n"+"\tbackground: #eeeeee;\n"+"\tborder: 1px solid DarkGray;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .currentTag   {\n"+"\tfont-weight: bold;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .suggestionNumber {\n"+"\tcolor: #808080;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .numberedSuggestion{\n"+"\twhite-space: nowrap;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .intelliTaggerFooter {\n"+"\tmargin-top: 4px;\n"+"\tborder-top-width: thin;\n"+"\tborder-top-style: solid;\n"+"\tborder-top-color: #999999;\n"+"}\n"+".intelliTaggerSuggestions .favorites {\n"+"\tborder-bottom-width: thin;\n"+"\tborder-bottom-style: solid;\n"+"\tborder-bottom-color: #999999;\n"+"\tpadding-bottom: 2px;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .normalTags {\n"+"\tpadding-top: 2px;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .intelliTaggerFooter .button {\n"+"\tfont-size: 10px;\n"+"\n"+"\tpadding-left: 0.3em;\n"+"\tpadding-right: 0.3em;\n"+"}\n"+"\n"+"/*}}}*/\n";config.shadowTiddlers["IntelliTaggerMainTemplate"]="<!--\n"+"{{{\n"+"-->\n"+"<div class=\"favorites\" macro=\"intelliTagger action: showFavorites\"></div>\n"+"<div class=\"normalTags\" macro=\"intelliTagger action: showTags\"></div>\n"+"<!-- The Footer (with the Navigation) ============================================ -->\n"+"<table class=\"intelliTaggerFooter\" border=\"0\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\"><tbody>\n"+"  <tr>\n"+"\t<td align=\"left\">\n"+"\t\t<span macro=\"intelliTagger action: closeButton\"></span>\n"+"\t</td>\n"+"\t<td align=\"right\">\n"+"\t\t<span macro=\"intelliTagger action: version\"></span>, <span macro=\"intelliTagger action: copyright \"></span>\n"+"\t</td>\n"+"  </tr>\n"+"</tbody></table>\n"+"<!--\n"+"}}}\n"+"-->\n";config.shadowTiddlers["IntelliTaggerEditTagsTemplate"]="<!--\n"+"{{{\n"+"-->\n"+"<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler'></div>\n"+"<div class='title' macro='view title'></div>\n"+"<div class='tagged' macro='tags'></div>\n"+"<div class='viewer' macro='view text wikified'></div>\n"+"<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler'></div>\n"+"<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>\n"+"<!--\n"+"}}}\n"+"-->\n";config.shadowTiddlers["BSD open source license (abego Software)"]="See [[Licence|http://tiddlywiki.abego-software.de/#%5B%5BBSD%20open%20source%20license%5D%5D]].";config.shadowTiddlers["IntelliTaggerPlugin Documentation"]="[[Documentation on abego Software website|http://tiddlywiki.abego-software.de/doc/IntelliTagger.pdf]].";config.shadowTiddlers["IntelliTaggerPlugin SourceCode"]="[[Plugin source code on abego Software website|http://tiddlywiki.abego-software.de/archive/IntelliTaggerPlugin/Plugin-IntelliTagger-src.1.0.2.js]]\n";(function(){var _126=restart;restart=function(){setStylesheet(store.getTiddlerText("IntelliTaggerStyleSheet"),"IntelliTaggerStyleSheet");_126.apply(this,arguments);};})();}
// %/
/***
|''Name:''|IntelliTagsEditCommandPlugin|
|''Version:''|1.0.0 (2007-10-03)|
|''Type:''|plugin|
|''Description:''|A command for your tiddler's toolbar to directly edit the tiddler's tags using the IntelliTaggerPlugin, without switching to "edit mode".|
|''Source:''|http://tiddlywiki.abego-software.de/#IntelliTagsEditCommandPlugin|
|''Requires:''|IntelliTaggerPlugin http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin|
|''Author:''|Udo Borkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license (abego Software)]]|
|''~CoreVersion:''|2.0.8|
|''Browser:''|Firefox 1.5.0.2 or better|
***/
/***
!Using the "IntelliTagsEditCommandPlugin"
Add the command {{{intelliTagsEdit}}} into the 'macro' attribute of the 'toolbar' {{{<div...>}}} in your ViewTemplate.

''Example:''
{{{
<div class='toolbar' 
        macro='toolbar -closeTiddler closeOthers +editTiddler intelliTagsEdit permalink references jump'>
</div>
}}}

This adds a "tags" button to the toolbar of the tiddlers (next to the ''edit'' button). Pressing the "tags" button will open the input field for the tiddler's tags and let you edit the tags with all the [[IntelliTaggerPlugin|http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin]] features.
***/
/***
!Source Code
***/
//{{{
(function(){

if (!version.extensions.IntelliTaggerPlugin)
    throw Error("IntelliTagsEditCommandPlugin requires the IntelliTaggerPlugin (http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin)");

if (config.commands.intelliTagsEdit) 
    return;

config.commands.intelliTagsEdit = {
	text: "tags",
	tooltip: "edit the tags"
};

config.commands.intelliTagsEdit.handler = function(event,src,title) {
	var button = abego.IntelliTagger.createEditTagsButton(title, null, "tags", "edit the tags");
	button.onclick(event);
	return false;
};

})();
//}}}
本文源自 : http://blog.jollen.org/mt-tb.cgi/66

jollen 發表於 October 19, 2006 11:27 PM

在伺服器(server)技術的發展藍圖中(roadmap),虛擬伺服器(virtual server)是 Intel 近來所著墨的重點。由以往單一硬體對單一作業系統(operating system)的伺服器架構(1 physical server v.s. 1 OS),未來將會演進成為單一硬體對多個作業系統的架構(1 physical server v.s. multiple OS)。

Intel 的 Virtualization Technology 就是一個這樣的新技術。Intel 的 Virtualization Technology 可以讓處理器支援多個 OS,不過這其實是基於我們所熟悉的虛擬機器軟體(例如:VMware、QEMU、Xen等)才能達到的,所以這是一個由「processor + chipsets + BIOS + 虛擬機器軟體」互相運作所實現的技術。

Virtual Machine Monitor (VMM)

軟體實作的虛擬機器在此技術領域中被統稱為「VMM - Virtual Machine Monitor」,現在已經有支援 Intel Virtualization Technology 的 VMM 了,那就是知名的 Xen。相關的參考網址如下:

Extending Xen with Intel Virtualization Technology - http://www.intel.com/technology/itj/2006/v10i3/3-xen/1-abstract.htm
Xen - http://www.xensource.com/index.html

接下來,就是我們今天在網路上所看到的重點了!

KVM: Kernel-based Virtual Machine

今天,看到了 2.6 kernel 的 KVM patch。KVM(Kernel Virtual Machine)是 Intel's virtualization technology 的驅動程式!KVM 驅動程式目前支援 i386 與 x86_64 "host",且「All combinations are allowed except x86_64 guest on i386 host.」。

比較特殊的是 Linux 2.6 的 KVM 驅動程式支援三種模式:kernel mode、user mode 與 guest mode。KVM 驅動程式的 user-space 介面是 '/dev/kvm',因此 process 可以執行自己的 virtual machine,在一台電腦上也能執行多個 virtual machine。Guest mode:

    「Guest mode has its own address space mapping guest physical memory (which is accessible to user mode by mmap()ing /dev/kvm). Guest mode has no access to any I/O devices; any such access is intercepted and directed to user mode for emulation. 」。

取得 Patch 與追踪主題

[PATCH 0/7] KVM: Kernel-based Virtual Machine
[PATCH 1/7] KVM: userspace interface
[PATCH 2/7] KVM: Intel virtual mode extensions definitions
[PATCH 3/7] KVM: kvm data structures
[PATCH 5/7] KVM: mmu virtualization
[PATCH 6/7] KVM: x86 emulator
[PATCH 7/7] KVM: plumbing

關於更多 Intel 的 Virtualization Technology

可以參考的網址如下:

Make virtualization a reality - http://www.intel.com/cd/channel/reseller/asmo-na/eng/products/server/processors/250640.htm
Server Virtualization Technology - http://www.intel.com/business/bss/products/server/virtualization_wp.pdf



[img[img/lpic101/1.PNG]]
<<toBalaNotes "01">>

///%01
//%/
[img[img/lpic101/2.PNG]]
<<toBalaNotes "02">>
///%02
//%/
[img[img/lpic101/3.PNG]]
<<toBalaNotes "03">>
///%03
//%/
[img[img/lpic101/4.PNG]]
<<toBalaNotes "04">>
///%04
//%/
[img[img/lpic101/5.PNG]]
<<toBalaNotes "05">>

///%05
//%/
[img[img/lpic101/6.PNG]]
<<toBalaNotes "06">>

///%06
//%/
[img[img/lpic101/7.PNG]]
<<toBalaNotes "07">>

///%07
//%/
[img[img/lpic101/8.PNG]]
<<toBalaNotes "08">>

///%08
//%/
[img[img/lpic101/9.PNG]]
<<toBalaNotes "09">>

///%09
//%/
[img[img/lpic101/10.PNG]]
<<toBalaNotes "10">>

///%10
//%/
[img[img/lpic101/11.PNG]]
<<toBalaNotes "11">>

///%11
//%/
[img[img/lpic101/12.PNG]]
<<toBalaNotes "12">>

///%12
//%/
[img[img/lpic101/13.PNG]]
<<toBalaNotes "13">>

///%13
//%/
[img[img/lpic101/14.PNG]]
<<toBalaNotes "14">>

///%14
//%/
[img[img/lpic101/15.PNG]]
<<toBalaNotes "15">>
///%15
//%/
[img[img/lpic101/16.PNG]]
<<toBalaNotes "16">>
///%16
//%/
[img[img/lpic101/17.PNG]]
<<toBalaNotes "17">>
///%17
//%/
[img[img/lpic101/18.PNG]]
<<toBalaNotes "18">>
///%18
//%/
[img[img/lpic101/19.PNG]]
<<toBalaNotes "19">>
///%19
//%/
[img[img/lpic101/20.PNG]]
<<toBalaNotes "20">>
///%20
//%/
[img[img/lpic101/21.PNG]]
<<toBalaNotes "21">>
///%21
//%/
[img[img/lpic101/22.PNG]]
<<toBalaNotes "22">>
///%22
//%/
[img[img/lpic101/24.PNG]]
<<toBalaNotes "24">>
///%24
//%/
[img[img/lpic101/25.PNG]]
<<toBalaNotes "25">>
///%25
//%/
[img[img/lpic101/26.PNG]]
<<toBalaNotes "26">>
///%26
//%/
[img[img/lpic101/30.PNG]]
<<toBalaNotes "30">>
///%30
//%/
[img[img/lpic101/31.PNG]]
<<toBalaNotes "31">>
///%31
//%/
[img[img/lpic101/32.PNG]]
<<toBalaNotes "32">>
///%32
//%/
[img[img/lpic101/33.PNG]]
<<toBalaNotes "33">>
///%33
//%/
[img[img/lpic101/34.PNG]]
<<toBalaNotes "34">>
///%34
//%/
[img[img/lpic101/35.PNG]]
<<toBalaNotes "35">>
///%35
//%/
[img[img/lpic101/36.PNG]]
<<toBalaNotes "36">>
///%36
//%/
[img[img/lpic101/37.PNG]]
<<toBalaNotes "37">>
///%37
//%/
[img[img/lpic101/38.PNG]]
<<toBalaNotes "38">>
///%38
//%/
[img[img/lpic101/39.PNG]]
<<toBalaNotes "39">>
///%39
//%/
[img[img/lpic101/40.PNG]]
<<toBalaNotes "40">>
///%40
//%/
[img[img/lpic101/41.PNG]]
<<toBalaNotes "41">>
///%41
//%/
[img[img/lpic101/42.PNG]]
<<toBalaNotes "42">>
///%42
//%/
[img[img/lpic101/43.PNG]]
<<toBalaNotes "43">>
///%43
//%/
[img[img/lpic101/44.PNG]]
<<toBalaNotes "44">>
///%44
//%/
[img[img/lpic101/45.PNG]]
<<toBalaNotes "45">>
///%45
//%/
[img[img/lpic101/46.PNG]]
<<toBalaNotes "46">>
///%46
//%/
[img[img/lpic101/51.PNG]]
<<toBalaNotes "51">>
///%51
//%/
[img[img/lpic101/52.PNG]]
<<toBalaNotes "52">>
///%52
//%/
[img[img/lpic101/53.PNG]]
<<toBalaNotes "53">>
///%53
//%/
[img[img/lpic101/54.PNG]]
<<toBalaNotes "54">>
///%54
//%/
[img[img/lpic101/55.PNG]]
<<toBalaNotes "55">>
///%55
//%/
[img[img/lpic101/56.PNG]]
<<toBalaNotes "56">>
///%56
//%/
[img[img/lpic101/57.PNG]]
<<toBalaNotes "57">>
///%57
//%/
[img[img/lpic101/58.PNG]]
<<toBalaNotes "58">>
///%52
//%/

///%58
//%/
[img[img/lpic101/59.PNG]]
<<toBalaNotes "59">>

///%59
//%/
[img[img/lpic101/60.PNG]]
<<toBalaNotes "60">>

///%60
//%/
[img[img/lpic101/61.PNG]]
<<toBalaNotes "61">>

///%61
//%/
[img[img/lpic101/62.PNG]]
<<toBalaNotes "62">>


///%62
//%/
[img[img/lpic101/63.PNG]]
<<toBalaNotes "63">>

///%63
//%/
[img[img/lpic101/64.PNG]]
<<toBalaNotes "64">>

///%64
//%/
[img[img/lpic101/65.PNG]]
<<toBalaNotes "65">>
///%65
//%/
[img[img/lpic101/66.PNG]]
<<toBalaNotes "66">>

///%66
//%/
[img[img/lpic101/67.PNG]]
<<toBalaNotes "67">>
///%67
//%/
[img[img/lpic101/68.PNG]]
<<toBalaNotes "68">>
///%68
//%/
[img[img/lpic101/69.PNG]]
<<toBalaNotes "69">>
///%69
//%/
[img[img/lpic101/70.PNG]]
<<toBalaNotes "70">>
///%70
//%/
[img[img/lpic101/71.PNG]]
<<toBalaNotes "71">>
///%71
//%/
[img[img/lpic101/72.PNG]]
<<toBalaNotes "72">>
///%72
//%/
[img[img/lpic101/73.PNG]]
<<toBalaNotes "73">>
///%73
//%/
[img[img/lpic101/74.PNG]]
<<toBalaNotes "74">>
///%74
//%/
[img[img/lpic101/75.PNG]]
<<toBalaNotes "75">>
///%75
//%/
[img[img/lpic101/76.PNG]]
<<toBalaNotes "76">>
///%76
//%/
[img[img/lpic101/77.PNG]]
<<toBalaNotes "77">>
///%77
//%/
[img[img/lpic101/78.PNG]]
<<toBalaNotes "78">>
///%78
//%/
[img[img/lpic101/79.PNG]]
<<toBalaNotes "79">>
///%79
//%/
[img[img/lpic101/80.PNG]]
<<toBalaNotes "80">>
///%80
//%/
[img[img/lpic101/81.PNG]]
<<toBalaNotes "81">>
///%81
//%/
[img[img/lpic101/82.PNG]]
<<toBalaNotes "82">>
///%82
//%/
[img[img/lpic101/83.PNG]]
<<toBalaNotes "83">>
///%83
//%/
[img[img/lpic101/84.PNG]]
<<toBalaNotes "84">>
///%84
//%/
[img[img/lpic101/85.PNG]]
<<toBalaNotes "85">>
///%85
//%/
[img[img/lpic101/86.PNG]]
<<toBalaNotes "86">>
///%86
//%/
[img[img/lpic101/87.PNG]]
<<toBalaNotes "87">>
///%87
//%/
[img[img/lpic101/88.PNG]]
<<toBalaNotes "88">>
///%88
//%/
[img[img/lpic101/89.PNG]]
<<toBalaNotes "89">>
///%89
//%/
[img[img/lpic101/90.PNG]]
<<toBalaNotes "90">>
///%90
//%/
[img[img/lpic101/91.PNG]]
<<toBalaNotes "91">>
///%91
//%/
[img[img/lpic101/92.PNG]]
<<toBalaNotes "92">>
///%92
//%/
[img[img/lpic101/93.PNG]]
<<toBalaNotes "93">>
///%93
//%/
[img[img/lpic101/94.PNG]]
<<toBalaNotes "94">>
///%94
//%/
[img[img/lpic101/95.PNG]]
<<toBalaNotes "95">>
///%95
//%/
[img[img/lpic101/96.PNG]]
<<toBalaNotes "96">>
///%96
//%/
[img[img/lpic101/97.PNG]]
<<toBalaNotes "97">>
///%97
//%/
[img[img/lpic101/98.PNG]]
<<toBalaNotes "98">>
///%98
//%/
[img[img/lpic101/99.PNG]]
<<toBalaNotes "99">>
///%99
//%/
[img[img/lpic101/100.PNG]]
<<toBalaNotes "100">>

///%100
//%/
[img[img/lpic101/103.PNG]]
<<toBalaNotes "103">>
///%103
//%/
[img[img/lpic101/110.PNG]]
<<toBalaNotes "110">>

///%110
//%/
[img[img/lpic101/113.PNG]]
<<toBalaNotes "113">>

///%113
//%/
[img[img/lpic101/114.PNG]]
<<toBalaNotes "114">>

///%114
//%/
[img[img/lpic101/115.PNG]]
<<toBalaNotes "115">>

///%115
//%/
[img[img/lpic101/116.PNG]]
<<toBalaNotes "116">>

///%116
//%/
[img[img/lpic101/118.PNG]]
<<toBalaNotes "118">>

///%118
//%/
[img[img/lpic101/119.PNG]]
<<toBalaNotes "119">>

///%119
//%/
[img[img/lpic101/121.PNG]]
<<toBalaNotes "121">>

///%121
//%/
[img[img/lpic101/122.PNG]]
<<toBalaNotes "122">>

///%122
//%/
[img[img/lpic101/123.PNG]]
<<toBalaNotes "123">>

///%123
//%/
[img[img/lpic101/124.PNG]]
<<toBalaNotes "124">>

///%124
//%/
[img[img/lpic101/125.PNG]]
<<toBalaNotes "125">>

///%125
//%/
[img[img/lpic101/126.PNG]]
<<toBalaNotes "126">>


///%126
//%/
[img[img/lpic101/127.PNG]]
<<toBalaNotes "127">>

///%127
//%/
[img[img/lpic101/129.PNG]]
<<toBalaNotes "129">>
///%129
//%/
[img[img/lpic101/130.PNG]]
<<toBalaNotes "130">>

///%130
//%/
[img[img/lpic101/131.PNG]]
<<toBalaNotes "131">>

///%131
//%/
[img[img/lpic101/132.PNG]]
<<toBalaNotes "132">>
///%132
//%/
[img[img/lpic101/133.PNG]]
<<toBalaNotes "133">>

///%133
//%/
[img[img/lpic101/134.PNG]]
<<toBalaNotes "134">>

///%134
//%/
[img[img/lpic101/135.PNG]]
<<toBalaNotes "135">>

///%135
//%/
[img[img/lpic102/33.PNG]]
<<toBalaNotes "033">>


///%033
//%/

/***
|Name|LoadTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#LoadTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#LoadTiddlersPluginInfo|
|Version|3.6.2|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Options|##Configuration|
|Description|macro for automated updates or one-click installations of tiddlers from remote sources|
***/
//{{{
version.extensions.loadTiddlers = {major: 3, minor: 6, revision: 2, date: new Date(2008,8,5)};

config.macros.loadTiddlers = {
	label: "",
	tip: "add/update tiddlers from '%0'",
	lockedTag: "noReload",	// if existing tiddler has this tag value, don't overwrite it, even if inbound tiddler is newer
	askMsg: "Please enter a local path/filename or a remote URL",
	openMsg: "Opening %0",
	openErrMsg: "Could not open %0 - error=%1",
	readMsg: "Read %0 bytes from %1",
	foundMsg: "Found %0 tiddlers in %1",
	nochangeMsg: "'%0' is up-to-date... skipped.",
	lockedMsg: "'%0' is tagged '%1'... skipped.",
	skippedMsg: "skipped (cancelled by user)",
	loadedMsg: "Loaded %0 of %1 tiddlers from %2",
	reportTitle: "ImportedTiddlers",
	warning: "Warning!!  Processing '%0' as a systemConfig (plugin) tiddler may produce unexpected results! Are you sure you want to proceed?",
	handler: function(place,macroName,params) {
		var label=(params[0] && params[0].substr(0,6)=='label:')?params.shift().substr(6):this.label;
		var tip=(params[0] && params[0].substr(0,7)=='prompt:')?params.shift().substr(7):this.tip;
		var filter="updates";
		if (params[0] && (params[0]=='all' || params[0]=='new' || params[0]=='changes' || params[0]=='updates'
			|| params[0].substr(0,8)=='tiddler:' || params[0].substr(0,4)=='tag:'))
			filter=params.shift();
		var src=params.shift(); if (!src || !src.length) return; // filename is required
		var quiet=(params[0]=="quiet"); if (quiet) params.shift();
		var ask=(params[0]=="confirm"); if (ask) params.shift();
		var force=(params[0]=="force"); if (force) params.shift();
		var init=(params[0]=="init"); if (init) params.shift();
		var noreport=(params[0]=="noreport"); if (noreport) params.shift();
		this.newTags=[]; if (params[0]) this.newTags=params; // any remaining params are used as "autotags"
		if (label.trim().length) {
			// link triggers load tiddlers from another file/URL and then applies filtering rules to add/replace tiddlers in the store
			createTiddlyButton(place,label.format([src.replace(/%20/g," ")]),tip.format([src.replace(/%20/g," ")]), function() {
				if (src=="ask") src=prompt(this.askMsg);
				config.macros.loadTiddlers.loadFile(src,config.macros.loadTiddlers.doImport,{quiet:quiet,ask:ask,filter:filter,force:force,init:init,noreport:noreport});
			})
		}
		else {
			// load tiddlers from another file/URL and then apply filtering rules to add/replace tiddlers in the store
			if (src=="ask") src=prompt(this.askMsg);
			config.macros.loadTiddlers.loadFile(src,config.macros.loadTiddlers.doImport,{quiet:quiet,ask:ask,filter:filter,force:force,init:init,noreport:noreport});
		}
	},
	loadFile: function(src,callback,params) {
		var quiet=params.quiet;
		if (src==undefined || !src.length) return null; // filename is required
		if (!quiet) clearMessage();
		if (!quiet) displayMessage(this.openMsg.format([src.replace(/%20/g," ")]));
		if (src.substr(0,5)!="http:" && src.substr(0,5)!="file:") { // if not a URL, read from local filesystem
			var txt=loadFile(src);
			if (!txt) { // file didn't load, might be relative path.. try fixup
				var pathPrefix=document.location.href;  // get current document path and trim off filename
				var slashpos=pathPrefix.lastIndexOf("/"); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf("\\"); 
				if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
				src=pathPrefix+src;
				if (pathPrefix.substr(0,5)!="http:") src=getLocalPath(src);
				var txt=loadFile(src);
			}
			if (!txt) { // file still didn't load, report error
				if (!quiet) displayMessage(this.openErrMsg.format([src.replace(/%20/g," "),"(unknown)"]));
			} else {
				if (!quiet) displayMessage(this.readMsg.format([txt.length,src.replace(/%20/g," ")]));
				if (callback) callback(true,params,convertUTF8ToUnicode(txt),src,null);
			}
		} else {
			var name=config.options.txtRemoteUsername; var pass=config.options.txtRemotePassword;
			var x=doHttp("GET",src,null,null,name,pass,callback,params,null);
		}
	},
	readTiddlersFromHTML: function(html) {
		// for TW2.2+
		if (TiddlyWiki.prototype.importTiddlyWiki!=undefined) {
			var remoteStore=new TiddlyWiki();
			remoteStore.importTiddlyWiki(html);
			return remoteStore.getTiddlers("title");	
		}
	},
	doImport: function(status,params,html,src,xhr) {
		var quiet=params.quiet;
		var ask=params.ask;
		var filter=params.filter;
		var force=params.force;
		var init=params.init;
		var noreport=params.noreport;
		var tiddlers = config.macros.loadTiddlers.readTiddlersFromHTML(html);
		var count=tiddlers?tiddlers.length:0;
		var querypos=src.lastIndexOf("?"); if (querypos!=-1) src=src.substr(0,querypos);
		if (!quiet) displayMessage(config.macros.loadTiddlers.foundMsg.format([count,src.replace(/%20/g," ")]));
		store.suspendNotifications();
		var count=0;
		if (tiddlers) for (var t=0;t<tiddlers.length;t++) {
			var inbound = tiddlers[t];
			var theExisting = store.getTiddler(inbound.title);
			if (inbound.title==config.macros.loadTiddlers.reportTitle)
				continue; // skip "ImportedTiddlers" history from the other document...
			if (theExisting && theExisting.tags.contains(config.macros.loadTiddlers.lockedTag)) {
				if (!quiet) displayMessage(config.macros.loadTiddlers.lockedMsg.format([theExisting.title,config.macros.loadTiddlers.lockedTag]));
				continue; // skip existing tiddler if tagged with 'noReload'
			}
			// apply the all/new/changes/updates filter (if any)
			if (filter && filter!="all") {
				if ((filter=="new") && theExisting) // skip existing tiddlers
					continue;
				if ((filter=="changes") && !theExisting) // skip new tiddlers
					continue;
				if ((filter.substr(0,4)=="tag:") && inbound.tags.indexOf(filter.substr(4))==-1) // must match specific tag value
					continue;
				if ((filter.substr(0,8)=="tiddler:") && inbound.title!=filter.substr(8)) // must match specific tiddler name
					continue;
				if (!force && store.tiddlerExists(inbound.title) && ((theExisting.modified.getTime()-inbound.modified.getTime())>=0))
					{ if (!quiet) displayMessage(config.macros.loadTiddlers.nochangeMsg.format([inbound.title])); continue; }
			}
			// get confirmation if required
			if (ask && !confirm((theExisting?"Update":"Add")+" tiddler '"+inbound.title+"'\nfrom "+src.replace(/%20/g," ")+"\n\nOK to proceed?"))
				{ tiddlers[t].status=config.macros.loadTiddlers.skippedMsg; continue; }
			// DO IT!
			var tags=Array.concat(inbound.tags,config.macros.loadTiddlers.newTags);
	                store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, tags, inbound.fields, true, inbound.created);
	                store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value - needed for TW2.1.3 or earlier
			tiddlers[t].status=theExisting?"updated":"added"
			if (init && tags.contains("systemConfig") && !tags.contains("systemConfigDisable")) {
				var ok=true;
				if (ask||!quiet) ok=confirm(config.macros.loadTiddlers.warning.format([inbound.title]))
				if (ok) { // run the plugin
					try { window.eval(inbound); tiddlers[t].status+=" (plugin initialized)"; }
					catch(ex) { displayMessage(config.messages.pluginError.format([exceptionText(ex)])); }
				}
			}
			count++;
		}
		store.resumeNotifications();
		if (count) {
			// refresh display
			store.setDirty(true); store.notifyAll();
			// generate a report
			if (!noreport) config.macros.loadTiddlers.report(src,tiddlers,count,quiet);
		}
		// always show final message when tiddlers were actually loaded
		if (!quiet||count) displayMessage(config.macros.loadTiddlers.loadedMsg.format([count,tiddlers.length,src.replace(/%20/g," ")]));
	},
	report: function(src,tiddlers,count,quiet) {
		// format the new report content
		var newText = "On "+(new Date()).toLocaleString()+", ";
		newText += config.options.txtUserName+" loaded "+count+" tiddlers ";
		newText += "from\n[["+src+"|"+src+"]]:\n";
		newText += "<<<\n";
		for (var t=0; t<tiddlers.length; t++)
			if (tiddlers[t].status)
				newText += "#[["+tiddlers[t].title+"]] - "+tiddlers[t].status+"\n";
		newText += "<<<\n";
		// get current report (if any)
		var title=config.macros.loadTiddlers.reportTitle;
		var currText="";
		var theReport = store.getTiddler(title);
		if (theReport) currText=((theReport.text!="")?'\n----\n':"")+theReport.text;
		// update the ImportedTiddlers content and show the tiddler
		store.saveTiddler(title, title, newText+currText, config.options.txtUserName, new Date(), theReport?theReport.tags:null, theReport?theReport.fields:null);
		if (!quiet) { story.displayTiddler(null,title,1,null,null,false); story.refreshTiddler(title,1,true); }
	}
}
//}}}
<<tagsTree twcms "" 1 4 index label>>
<<tagsTree lsys0101 "" 1 4 index label>>
<<tagsTree lsys0102 "" 1 4 index label>>
<<tagsTree lsys0103 "" 1 4 index label>>
<<tagsTree lsys0104 "" 1 4 index label>>
<<tagsTree lsys0105 "" 1 4 index label>>
<<tagsTree lsys0106 "" 1 4 index label>>
<<tagsTree lsys0107 "" 1 4 index label>>
<<tagsTree lsys0108 "" 1 4 index label>>
<<tagsTree lsys0109 "" 1 4 index label>>
<<tagsTree lsys0110 "" 1 4 index label>>
<<tagsTree KMKConfig "" 1 4 index label>>
<<tagsTree menu "" 1 4 index label>>
<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml'/>
<!--}}}-->

<!--{{{-->
<style type="text/css">
#contentWrapper {display:none;}
</style>

<div id="SplashScreen" style="border: 3px solid #ccc; display: block; text-align: center; width: 320px; margin: 100px auto; padding: 50px; color:#000; font-size: 28px; font-family:Tahoma; background-color:#eee;">
<b>toBala KM King</b><br><br><img src="loader.gif"><br>
<span style="font-size: 14px; color:red;">Requires Javascript.</span>
</div>
<!--}}}-->
這些設定將暫存於瀏覽器
請簽名<<option txtUserName>>
 (範例:WikiWord)

 <<option chkSaveBackups>> 儲存備份
 <<option chkAutoSave>> 自動儲存
 <<option chkRegExpSearch>> 正規式搜尋
 <<option chkCaseSensitiveSearch>> 區分大小寫搜尋
 <<option chkAnimate>> 使用動畫顯示
----
 [[進階選項|AdvancedOptions]]
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>

<div id='toolBar' refresh='content' force='true' tiddler='toBalaToolBar'></div>
<div id='mainMenu' refresh='content' force='true' tiddler='MainMenu'></div>

<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlersBar' refresh='none' ondblclick='config.macros.tiddlersBar.onTiddlersBarAction(event)'></div>
<div id='tiddlerDisplay'></div>
</div>

<iframe id='ApplicationArea' width='100%' height='100%'></iframe>
<!--}}}-->
//{{{
//============================================================================
//                           PartTiddlerPlugin

// Ensure that the PartTiddler Plugin is only installed once.
//
if (!version.extensions.PartTiddlerPlugin) {

version.extensions.PartTiddlerPlugin = {
    major: 1, minor: 0, revision: 9,
    date: new Date(2007, 6, 14), 
    type: 'plugin',
    source: "http://tiddlywiki.abego-software.de/#PartTiddlerPlugin"
};

if (!window.abego) window.abego = {};
if (version.major < 2) alertAndThrow("PartTiddlerPlugin requires TiddlyWiki 2.0 or newer.");

//============================================================================
// Common Helpers

// Looks for the next newline, starting at the index-th char of text. 
//
// If there are only whitespaces between index and the newline 
// the index behind the newline is returned, 
// otherwise (or when no newline is found) index is returned.
//
var skipEmptyEndOfLine = function(text, index) {
	var re = /(\n|[^\s])/g;
	re.lastIndex = index;
	var result = re.exec(text);
	return (result && text.charAt(result.index) == '\n') 
			? result.index+1
			: index;
}


//============================================================================
// Constants

var partEndOrStartTagRE = /(<\/part>)|(<part(?:\s+)((?:[^>])+)>)/mg;
var partEndTagREString = "<\\/part>";
var partEndTagString = "</part>";

//============================================================================
// Plugin Specific Helpers

// Parse the parameters inside a <part ...> tag and return the result.
//
// @return [may be null] {partName: ..., isHidden: ...}
//
var parseStartTagParams = function(paramText) {
	var params = paramText.readMacroParams();
	if (params.length == 0 || params[0].length == 0) return null;
	
	var name = params[0];
	var paramsIndex = 1;
	var hidden = false;
	if (paramsIndex < params.length) {
		hidden = params[paramsIndex] == "hidden";
		paramsIndex++;
	}
	
	return {
		partName: name, 
		isHidden: hidden
	};
}

// Returns the match to the next (end or start) part tag in the text, 
// starting the search at startIndex.
// 
// When no such tag is found null is returned, otherwise a "Match" is returned:
// [0]: full match
// [1]: matched "end" tag (or null when no end tag match)
// [2]: matched "start" tag (or null when no start tag match)
// [3]: content of start tag (or null if no start tag match)
//
var findNextPartEndOrStartTagMatch = function(text, startIndex) {
	var re = new RegExp(partEndOrStartTagRE);
	re.lastIndex = startIndex;
	var match = re.exec(text);
	return match;
}

//============================================================================
// Formatter

// Process the <part ...> ... </part> starting at (w.source, w.matchStart) for formatting.
//
// @return true if a complete part section (including the end tag) could be processed, false otherwise.
//
var handlePartSection = function(w) {
	var tagMatch = findNextPartEndOrStartTagMatch(w.source, w.matchStart);
	if (!tagMatch) return false;
	if (tagMatch.index != w.matchStart || !tagMatch[2]) return false;

	// Parse the start tag parameters
	var arguments = parseStartTagParams(tagMatch[3]);
	if (!arguments) return false;
	
	// Continue processing
	var startTagEndIndex = skipEmptyEndOfLine(w.source, tagMatch.index + tagMatch[0].length);
	var endMatch = findNextPartEndOrStartTagMatch(w.source, startTagEndIndex);
	if (endMatch && endMatch[1]) {
		if (!arguments.isHidden) {
			w.nextMatch = startTagEndIndex;
			w.subWikify(w.output,partEndTagREString);
		}
		w.nextMatch = skipEmptyEndOfLine(w.source, endMatch.index + endMatch[0].length);
		
		return true;
	}
	return false;
}

config.formatters.push( {
    name: "part",
    match: "<part\\s+[^>]+>",
	
	handler: function(w) {
		if (!handlePartSection(w)) {
			w.outputText(w.output,w.matchStart,w.matchStart+w.matchLength);
		}
	}
} )

//============================================================================
// Extend "fetchTiddler" functionality to also recognize "part"s of tiddlers 
// as tiddlers.

var currentParent = null; // used for the "." parent (e.g. in the "tiddler" macro)

// Return the match to the first <part ...> tag of the text that has the
// requrest partName.
//
// @return [may be null]
//
var findPartStartTagByName = function(text, partName) {
	var i = 0;
	
	while (true) {
		var tagMatch = findNextPartEndOrStartTagMatch(text, i);
		if (!tagMatch) return null;

		if (tagMatch[2]) {
			// Is start tag
	
			// Check the name
			var arguments = parseStartTagParams(tagMatch[3]);
			if (arguments && arguments.partName == partName) {
				return tagMatch;
			}
		}
		i = tagMatch.index+tagMatch[0].length;
	}
}

// Return the part "partName" of the given parentTiddler as a "readOnly" Tiddler 
// object, using fullName as the Tiddler's title. 
//
// All remaining properties of the new Tiddler (tags etc.) are inherited from 
// the parentTiddler.
// 
// @return [may be null]
//
var getPart = function(parentTiddler, partName, fullName) {
	var text = parentTiddler.text;
	var startTag = findPartStartTagByName(text, partName);
	if (!startTag) return null;
	
	var endIndexOfStartTag = skipEmptyEndOfLine(text, startTag.index+startTag[0].length);
	var indexOfEndTag = text.indexOf(partEndTagString, endIndexOfStartTag);

	if (indexOfEndTag >= 0) {
		var partTiddlerText = text.substring(endIndexOfStartTag,indexOfEndTag);
		var partTiddler = new Tiddler();
		partTiddler.set(
						fullName,
						partTiddlerText,
						parentTiddler.modifier,
						parentTiddler.modified,
						parentTiddler.tags,
						parentTiddler.created);
		partTiddler.abegoIsPartTiddler = true;
		return partTiddler;
	}
	
	return null;
}

// Hijack the store.fetchTiddler to recognize the "part" addresses.
//
var hijackFetchTiddler = function() {
	var oldFetchTiddler = store.fetchTiddler ;
	store.fetchTiddler = function(title) {
		var result = oldFetchTiddler.apply(this, arguments);
		if (!result && title) {
			var i = title.lastIndexOf('/');
			if (i > 0) {
				var parentName = title.substring(0, i);
				var partName = title.substring(i+1);
				var parent = (parentName == ".") 
						? store.resolveTiddler(currentParent)
						: oldFetchTiddler.apply(this, [parentName]);
				if (parent) {
					return getPart(parent, partName, parent.title+"/"+partName);
				}
			}
		}
		return result;	
	};
};

// for debugging the plugin is not loaded through the systemConfig mechanism but via a script tag. 
// At that point in the "store" is not yet defined. In that case hijackFetchTiddler through the restart function.
// Otherwise hijack now.
if (!store) {
	var oldRestartFunc = restart;
	window.restart = function() {
		hijackFetchTiddler();
		oldRestartFunc.apply(this,arguments);
	};
} else
	hijackFetchTiddler();




// The user must not edit a readOnly/partTiddler
//

config.commands.editTiddler.oldIsReadOnlyFunction = Tiddler.prototype.isReadOnly;

Tiddler.prototype.isReadOnly = function() {
	// Tiddler.isReadOnly was introduced with TW 2.0.6.
	// For older version we explicitly check the global readOnly flag
	if (config.commands.editTiddler.oldIsReadOnlyFunction) {
		if (config.commands.editTiddler.oldIsReadOnlyFunction.apply(this, arguments)) return true;
	} else {
		if (readOnly) return true;
	}

	return this.abegoIsPartTiddler;
}

config.commands.editTiddler.handler = function(event,src,title)
{
	var t = store.getTiddler(title);
	// Edit the tiddler if it either is not a tiddler (but a shadowTiddler)
	// or the tiddler is not readOnly
	if(!t || !t.abegoIsPartTiddler)
		{
		clearMessage();
		story.displayTiddler(null,title,DEFAULT_EDIT_TEMPLATE);
		story.focusTiddler(title,"text");
		return false;
		}
}

// To allow the "./partName" syntax in macros we need to hijack 
// the invokeMacro to define the "currentParent" while it is running.
// 
var oldInvokeMacro = window.invokeMacro;
function myInvokeMacro(place,macro,params,wikifier,tiddler) {
	var oldCurrentParent = currentParent;
	if (tiddler) currentParent = tiddler;
	try {
		oldInvokeMacro.apply(this, arguments);
	} finally {
		currentParent = oldCurrentParent;
	}
}
window.invokeMacro = myInvokeMacro;

// To correctly support the "./partName" syntax while refreshing we need to hijack 
// the config.refreshers.tiddlers to define the "currentParent" while it is running.
// 
(function() {
	var oldTiddlerRefresher= config.refreshers.tiddler;
	config.refreshers.tiddler = function(e,changeList) {
		var oldCurrentParent = currentParent;
		try {
			currentParent = e.getAttribute("tiddler");
			return oldTiddlerRefresher.apply(this,arguments);
		} finally {
			currentParent = oldCurrentParent;
		}
	};
})();

// Support "./partName" syntax inside <<tabs ...>> macro
(function() {
	var extendRelativeNames = function(e, title) {
		var nodes = e.getElementsByTagName("a");
		for(var i=0; i<nodes.length; i++) {
			var node = nodes[i];
			var s = node.getAttribute("content");
			if (s && s.indexOf("./") == 0)
				node.setAttribute("content",title+s.substr(1));
		}
	};
	var oldHandler = config.macros.tabs.handler;
	config.macros.tabs.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
		var result = oldHandler.apply(this,arguments);
		if (tiddler)
			extendRelativeNames(place, tiddler.title);
		return result;
	};
})();

// Scroll the anchor anchorName in the viewer of the given tiddler visible.
// When no tiddler is defined use the tiddler of the target given event is used.
window.scrollAnchorVisible = function(anchorName, tiddler, evt) {
	var tiddlerElem = null;
	if (tiddler) {
		tiddlerElem = document.getElementById(story.idPrefix + tiddler);
	}
	if (!tiddlerElem && evt) {
		var target = resolveTarget(evt);
		tiddlerElem = story.findContainingTiddler(target);
	}
	if (!tiddlerElem) return;

	var children = tiddlerElem.getElementsByTagName("a");
	for (var i = 0; i < children.length; i++) {
		var child = children[i];
		var name = child.getAttribute("name");
		if (name == anchorName) {
			var y = findPosY(child);
			window.scrollTo(0,y);
			return;
		}
	}
}

} // of "install only once"
//}}}
<<tabs txtMainTab "最近更新" "依更新日期排序" TabTimeline "分類" "所有標籤" TabTags "設定文章" "說所有設定文章" TabMoreShadowed>>
V1.1 (2010/04/02)
Linux 系統基礎- 學習筆記本
/***
|''Name:''|SparklinePlugin|
|''Description:''|Sparklines macro|
***/
//{{{
if(!version.extensions.SparklinePlugin) {
version.extensions.SparklinePlugin = {installed:true};

//--
//-- Sparklines
//--

config.macros.sparkline = {};
config.macros.sparkline.handler = function(place,macroName,params)
{
	var data = [];
	var min = 0;
	var max = 0;
	var v;
	for(var t=0; t<params.length; t++) {
		v = parseInt(params[t]);
		if(v < min)
			min = v;
		if(v > max)
			max = v;
		data.push(v);
	}
	if(data.length < 1)
		return;
	var box = createTiddlyElement(place,"span",null,"sparkline",String.fromCharCode(160));
	box.title = data.join(",");
	var w = box.offsetWidth;
	var h = box.offsetHeight;
	box.style.paddingRight = (data.length * 2 - w) + "px";
	box.style.position = "relative";
	for(var d=0; d<data.length; d++) {
		var tick = document.createElement("img");
		tick.border = 0;
		tick.className = "sparktick";
		tick.style.position = "absolute";
		tick.src = "data:image/gif,GIF89a%01%00%01%00%91%FF%00%FF%FF%FF%00%00%00%C0%C0%C0%00%00%00!%F9%04%01%00%00%02%00%2C%00%00%00%00%01%00%01%00%40%02%02T%01%00%3B";
		tick.style.left = d*2 + "px";
		tick.style.width = "2px";
		v = Math.floor(((data[d] - min)/(max-min)) * h);
		tick.style.top = (h-v) + "px";
		tick.style.height = v + "px";
		box.appendChild(tick);
	}
};


}
//}}}
/***

''Inspired by [[TiddlyPom|http://www.warwick.ac.uk/~tuspam/tiddlypom.html]]''

|Name|SplashScreenPlugin|
|Created by|SaqImtiaz|
|Location|http://tw.lewcid.org/#SplashScreenPlugin|
|Version|0.21 |
|Requires|~TW2.08+|
!Description:
Provides a simple splash screen that is visible while the TW is loading.

!Installation
Copy the source text of this tiddler to your TW in a new tiddler, tag it with systemConfig and save and reload. The SplashScreen will now be installed and will be visible the next time you reload your TW.

!Customizing
Once the SplashScreen has been installed and you have reloaded your TW, the splash screen html will be present in the MarkupPreHead tiddler. You can edit it and customize to your needs.

!History
* 20-07-06 : version 0.21, modified to hide contentWrapper while SplashScreen is displayed.
* 26-06-06 : version 0.2, first release

!Code
***/
//{{{
var old_lewcid_splash_restart=restart;

restart = function()
{   if (document.getElementById("SplashScreen"))
        document.getElementById("SplashScreen").style.display = "none";
      if (document.getElementById("contentWrapper"))
        document.getElementById("contentWrapper").style.display = "block";
    
    old_lewcid_splash_restart();
   
    if (splashScreenInstall)
       {if(config.options.chkAutoSave)
			{saveChanges();}
        displayMessage("TW SplashScreen has been installed, please save and refresh your TW.");
        }
}


var oldText = store.getTiddlerText("MarkupPreHead");
if (oldText.indexOf("SplashScreen")==-1)
   {var siteTitle = store.getTiddlerText("SiteTitle");
   var splasher='\n\n<style type="text/css">#contentWrapper {display:none;}</style><div id="SplashScreen" style="border: 3px solid #ccc; display: block; text-align: center; width: 320px; margin: 100px auto; padding: 50px; color:#000; font-size: 28px; font-family:Tahoma; background-color:#eee;"><b>'+siteTitle +'</b> is loading<blink> ...</blink><br><br><span style="font-size: 14px; color:red;">Requires Javascript.</span></div>';
   if (! store.tiddlerExists("MarkupPreHead"))
       {var myTiddler = store.createTiddler("MarkupPreHead");}
   else
      {var myTiddler = store.getTiddler("MarkupPreHead");}
      myTiddler.set(myTiddler.title,oldText+splasher,config.options.txtUserName,null,null);
      store.setDirty(true);
      var splashScreenInstall = true;
}
//}}}
ZDNet新聞專區:Mike Ricciuti 2008/10/01 13:27:02 不是人人都熱愛雲端運算,自由軟體基金會(FSF)創辦人兼GNU作業系統之父就說,雲端運算是件「蠢事」(stupidity),可能導致成本節節攀升。

Stallman在英國衛報周一登出的評論中說:「雲端運算有趣的是,我們已把雲端運算重新定義,把我們已經做的每一件事都包含在其中。」
 
雲端運算(cloud computing)是近年來電腦工業界提倡的一種觀念,也就是把大多數的運算馬力(有時也包括資料)移往伺服器,而這些伺服器由Google、微軟、Amazon等公司維護。最典型的雲端運算例子可能是Google提供的Gmail。

Stallman指出,雲端運算迫使民眾把自己資料的控制權交給第三者。他的反對意見與他長年來篤信非專屬軟體的信念相呼應。

他說:「你不該用網路應用程式來處理運算任務的一大理由,就是你會喪失控制權。這和使用專屬軟體一樣糟糕。」

他還說:「在自己的電腦上,用自己的一份自由軟體,做自己的運算。如果你用的是專屬軟體,或某某人的網路伺服器,你就失去防衛力,受制於開發那個軟體的人,不論他是何人。」

Stallman也駁斥雲端運算是資訊業大勢所需的說法。

他說:「(雲端運算)是蠢事,比蠢事還蠢,不過是行銷宣傳語罷了。有人說這是無可抗拒的潮流,不論你是聽誰這麼說,很可能只是想讓它實現的商業廣告宣傳罷了。」(唐慧文/譯) 


''不同的看法''

    * 嗯‧‧‧
      我不希望把滷肉飯的控制權交給樓下的攤販,所以我決定要自己做滷肉飯。
      我不希望滷肉飯中,飯的控制權交給嘉南平原的農民,所以我決定要自己種稻。
      我不希望滷肉飯中,滷肉的控制權交給養豬戶,所以我決定自己養豬。
      我不希望喝的牛奶中有三聚氫胺,所以我決定自己養牛。
      我不希望交由一個看不到,摸不到,聽不到的神祕力量控制我的生死,所以我決定自己控制我的生與死。
      控制與被控制的界線在哪裡?有誰可以真正凡事自己決定,自己控制一切的?
      我很佩服RMS,但是,搞到這種地步,會不會太精神官能症了一點?



/*{{{*/

/* 應用模式的樣式設定 */
#ApplicationArea {display:none;width:100px;height:100%;}


/* option 巨集文字欄位的長度 */
.txtOptionInput {width:40em;}


/* 主要項目樣式 

    在 Tiddler 中的使用格式如下 :
    {{item1{Item description}}}

*/
.item1{
 line-height:28px;
 font-weight:bold; 
 font-size:14px;
 border-left: 10px solid blue;
 margin:0px 0px 0px 0px;
 padding: 0px 0px 0px 3px;
 background-color:transparent;
}

/* 實作項目樣式 

    在 Tiddler 中的使用格式如下 :
    {{op1{operation description}}}

*/
.op1{
 line-height:28px;
 font-weight:bold; 
 font-size:14px;
 margin:0px 0px 0px 0px;
 padding: 0px 0px 0px 0px;
 background-color:transparent;
}


/*
Making preformated <pre> text wrap in CSS3, Mozilla, Opera and IE

word-wrap: break-word; - 視窗邊界換行,僅 IE 支援。也可以用 word-brak: break-all; 但不會保持英文單字的完整性。
white-space: pre; - 對某標籤作預先格式化,所有標準瀏覽器皆支援。
white-space: -moz-pre-wrap; - 預先格式化,但在元素邊界換行,僅 Mozilla (Firefox) 支援。
white-space: pre-wrap; - 預先格式化,但在元素邊界換行,僅 Opera 支援。
*/
.viewer pre {
  font-size:12px;
  white-space: pre-wrap;       /* css-3 */
  white-space: -moz-pre-wrap;  /* Mozilla, since 1999 */
  white-space: -pre-wrap;      /* Opera 4-6 */
  white-space: -o-pre-wrap;    /* Opera 7 */
  word-wrap: break-word;       /* Internet Explorer 5.5+ */
}
.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}


/*
無框線表格樣式設定, 以下是使用範例:

|!Col1|!Col2|!Col3|
|r1c1| r1r2c2 |r1c3|
|r2c1|~|r2c3|
|borderless|k    // 使用格式

*/
.borderless, .borderless table, .borderless td, .borderless tr, .borderless th, .borderless tbody { 
   border:0 !important; margin:0 !important; padding:2px !important; 
   td.vertical-align:top !important;margin-left: auto !important; 
   margin-right: auto !important;
}

.externalLink {text-decoration:none}

#toolBar { 
 background-color: #eee; 
 color:#ccc;
 width: auto;
 text-align:left;
 padding: 0.4em 0.6em 0.4em 0.6em;
}

h1,h2,h3 {padding-bottom:1px; margin-top:0.1em;margin-bottom:0.1em;}
h4,h5,h6 {margin-top:0.1em;}
h1 {font-size:1.2em;}
h2 {font-size:1.0em;}
h3 {font-size:1.0em;}
h4 {font-size:0.8em;}
h5 {font-size:.0.8em;}

.headerShadow {position:relative; padding:2.0em 0em 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:2.0em 0em 1em 1em; left:0px; top:0px;}

#mainMenu {
position:absolute; left:0; width:15.5em; text-align:left; line-height:1.2em; 
padding:1.0em 0.5em 0.2em 0.5em; font-size:1em;
}

#displayArea {margin:1em 1em 0em 17em;}

/*
 toBalaFile 巨集的 Style 設定
*/
.toBalaFile {background:#fff; border:0px solid #ccc; padding:1px 7px 1px 3px; margin:2px;}
.toBalaFileEdit {border:1px solid #841;padding:2px;margin:2px 5px 2px 5px;}
.toBalaFileCancel {border:1px solid #841;padding:2px;margin:2px 5px 2px 5px;}
.toBalaFileToolBar {background:#fff;border-bottom: 3px solid #841;padding:3px 0px 5px 0px;margin:5px 0px 0px 5px;}
.toBalaFileSave {border:1px solid #841;padding:2px;margin:2px 5px 2px 5px;}

/*}}}*/
/*{{{*/
/***** LAYOUT STYLES -  DO NOT EDIT! *****/
ul.suckerfish, ul.suckerfish ul {
	margin: 0;
	padding: 0;
	list-style: none;
	line-height:1.4em;
}

ul.suckerfish  li {
	display: inline-block; 
	display: block;
	float: left; 
}

ul.suckerfish li ul {
	position: absolute;
	left: -999em;
}

ul.suckerfish li:hover ul, ul.suckerfish li.sfhover ul {
	left: auto;
}

ul.suckerfish ul li {
	float: none;
	border-right: 0;
	border-left:0;
}

ul.suckerfish a, ul.suckerfish a:hover {
	display: block;
}

ul.suckerfish li a.tiddlyLink, ul.suckerfish li a, #mainMenu ul.suckerfish li a {font-weight:bold;}
/**** END LAYOUT STYLES *****/


/**** COLORS AND APPEARANCE - DEFAULT *****/
ul.suckerfish li a {
	padding: 0.5em 1.5em;
	color: #FFF;
	background: #0066aa;
	border-bottom: 0;
	font-weight:bold;
}

ul.suckerfish li:hover a, ul.suckerfish li.sfhover a{
	background: #00558F;
}

ul.suckerfish li:hover ul a, ul.suckerfish li.sfhover ul a{
	color: #000;
	background: #eff3fa;
	border-top:1px solid #FFF;
}

ul.suckerfish ul li a:hover {
	background: #e0e8f5;
}

ul.suckerfish li a{
	width:9em;
}

ul.suckerfish ul li a, ul.suckerfish ul li a:hover{
	display:inline-block;
	width:9em;
}

ul.suckerfish li {
	border-left: 1px solid #00558F;
}
/***** END COLORS AND APPEARANCE - DEFAULT *****/


/***** LAYOUT AND APPEARANCE: VERTICAL *****/
ul.suckerfish.vertical li{
	width:10em;
	border-left: 0px solid #00558f;
}

ul.suckerfish.vertical ul li, ul.suckerfish.vertical li a, ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a {
	border-left: 0.8em solid #00558f;
}

ul.suckerfish.vertical li a, ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a,  ul.suckerfish.vertical li.sfhover a:hover{
	width:8em;
}

ul.suckerfish.vertical {
	width:10em; text-align:left;
	float:left;
}

ul.suckerfish.vertical li a {
	padding: 0.5em 1em 0.5em 1em;
	border-top:1px solid  #fff;
}

ul.suckerfish.vertical, ul.suckerfish.vertical ul {
	line-height:1.4em;
}

ul.suckerfish.vertical li:hover ul, ul.suckerfish.vertical li.sfhover ul { 
	margin: -2.4em 0 0 10.9em;
}

ul.suckerfish.vertical li:hover ul li a, ul.suckerfish.vertical li.sfhover ul li a {
	border: 0px solid #FFF;
}

ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a{
	padding-right:1.1em;
}

ul.suckerfish.vertical li:hover ul li, ul.suckerfish.vertical li.sfhover ul li {
	border-bottom:1px solid  #fff;
}

/***** END LAYOUT AND APPEARANCE: VERTICAL *****/
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0em 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0em 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0em 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 .3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0em 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0em 0em 0em; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0em;}
.wizardFooter .status {padding:0em 0.4em 0em 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em 0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0em; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em 0.2em 0.2em 0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em 0.2em 0.2em 0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em 1em 1em 1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0em;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0em 0em 0.5em;}
.tab {margin:0em 0em 0em 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0em 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0em 1em;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0em 0.25em; padding:0em 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0em; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px 1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0em; right:0em;}
#backstageButton a {padding:0.1em 0.4em 0.1em 0.4em; margin:0.1em 0.1em 0.1em 0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; margin:0em 3em 0em 3em; padding:1em 1em 1em 1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em 0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
<<tabs txtMoreTab "未完成" "內容空白的文章" TabMoreMissing "未引用" "未被引用的文章" TabMoreOrphans "預設文章" "已預設內容的隱藏文章" TabMoreShadowed>>
<<list shadowed>>
<<allTags excludeLists>>
<<timeline>>
/***
|Name|TaggedTemplateTweak|
|Source|http://www.TiddlyTools.com/#TaggedTemplateTweak|
|Version|1.1.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Story.prototype.chooseTemplateForTiddler()|
|Description|use alternative ViewTemplate/EditTemplate for tiddler's tagged with specific tag values|
The core function, "story.chooseTemplateForTiddler(title,template)" is essentially a "pass-thru" that returns the same template it was given, and is provided by the core so that plugins can customize the template selection logic to select alternative templates, based on whatever programmatic criteria is appropriate.  This tweak extends story.chooseTemplateForTiddler() so that ''whenever a tiddler is marked with a specific tag value, it can be viewed and/or edited using alternatives to the standard tiddler templates.'' 
!!!!!Usage
<<<
Each alternative template is associated with a specific tiddler tag value by using that tag value as a prefix added to the standard TiddlyWiki template titles, [[ViewTemplate]] and [[EditTemplate]].

For example, any tiddlers that are tagged with ''<<tag media>>'' will look for alternative templates named [[mediaViewTemplate]] and [[mediaEditTemplate]].  Additionally, in order to find templates that have proper WikiWord tiddler titles (e.g., [[MediaViewTemplate]] and [[MediaEditTemplate]]), the plugin will also attempt to use a capitalized form of the tag value (e.g., ''Media'') as a prefix.  //This capitalization is for comparison purposes only and will not alter the actual tag values that are stored in the tiddler.//

If no matching alternative template can be found by using //any// of the tiddler's tags (either "as-is" or capitalized), the tiddler defaults to using the appropriate standard [[ViewTemplate]] or [[EditTemplate]] definition.

''To add your own custom templates:''
>First, decide upon a suitable tag keyword to uniquely identify your custom templates and create custom view and/or edit templates using that keyword as a prefix (e.g., "KeywordViewTemplate" and "KeywordEditTemplate").  Then, simply create a tiddler and tag it with your chosen keyword... that's it!  As long as the tiddler is tagged with your keyword, it will be displayed using the corresponding alternative templates.  If you remove the tag or rename/delete the alternative templates, the tiddler will revert to using the standard viewing and editing templates.
<<<
!!!!!Examples
<<<
|Sample tiddler| tag | view template | edit template |
|[[MediaSample - QuickTime]]| <<tag media>> | [[MediaViewTemplate]] | [[MediaEditTemplate]] |
|[[MediaSample - Windows]]| <<tag media>> | [[MediaViewTemplate]] | [[MediaEditTemplate]] |
|[[CDSample]]| <<tag CD>> | [[CDViewTemplate]] | [[CDEditTemplate]] |
|<<newTiddler label:"create new task..." title:SampleTask tag:task text:"Type some text and then press DONE to view the task controls">> | <<tag task>> | [[TaskViewTemplate]] | [[EditTemplate]] |

//(note: if these samples are not present in your document, please visit// http://www.TiddlyTools.com/ //to view these sample tiddlers on-line)//
<<<
!!!!!Revisions
<<<
2007.06.23 [1.1.0] re-written to use automatic 'tag prefix' search instead of hard coded check for each tag.  Allows new custom tags to be used without requiring code changes to this plugin.
2007.06.11 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.taggedTemplate= {major: 1, minor: 1, revision: 0, date: new Date(2007,6,18)};
Story.prototype.taggedTemplate_chooseTemplateForTiddler = Story.prototype.chooseTemplateForTiddler
Story.prototype.chooseTemplateForTiddler = function(title,template)
{
	// get default template from core
	var template=this.taggedTemplate_chooseTemplateForTiddler.apply(this,arguments);

	// if the tiddler to be rendered doesn't exist yet, just return core result
	var tiddler=store.getTiddler(title); if (!tiddler) return template;

	// look for template whose prefix matches a tag on this tiddler
	for (t=0; t<tiddler.tags.length; t++) {
		var tag=tiddler.tags[t];
		if (store.tiddlerExists(tag+template)) { template=tag+template; break; }
		// try capitalized tag (to match WikiWord template titles)
		var cap=tag.substr(0,1).toUpperCase()+tag.substr(1);
		if (store.tiddlerExists(cap+template)) { template=cap+template; break; }
	}

	return template;
}
//}}}
/***
|''Name:''|~TaggerPlugin|
|''Version:''|1.0.1 (2006-06-01)|
|''Source:''|http://tw.lewcid.org//#TaggerPlugin|
|''Author:''|SaqImtiaz|
|''Description:''|Provides a drop down listing current tiddler tags, and allowing toggling of tags.|
|''Documentation:''|[[TaggerPluginDocumentation]]|
|''Source Code:''|[[TaggerPluginSource]]|
|''~TiddlyWiki:''|Version 2.0.8 or better|
***/
// /%
config.tagger={defaults:{label:"Tags: ",tooltip:"Manage tiddler tags",taglist:"true",excludeTags:"",notags:"tiddler has no tags",aretags:"current tiddler tags:",toggletext:"add tags:"}};config.macros.tagger={};config.macros.tagger.arrow=(document.all?"▼":"▾");config.macros.tagger.handler=function(_1,_2,_3,_4,_5,_6){var _7=config.tagger.defaults;var _8=_5.parseParams("tagman",null,true);var _9=((_8[0].label)&&(_8[0].label[0])!=".")?_8[0].label[0]+this.arrow:_7.label+this.arrow;var _a=((_8[0].tooltip)&&(_8[0].tooltip[0])!=".")?_8[0].tooltip[0]:_7.tooltip;var _b=((_8[0].taglist)&&(_8[0].taglist[0])!=".")?_8[0].taglist[0]:_7.taglist;var _c=((_8[0].exclude)&&(_8[0].exclude[0])!=".")?(_8[0].exclude[0]).readBracketedList():_7.excludeTags.readBracketedList();if((_8[0].source)&&(_8[0].source[0])!="."){var _d=_8[0].source[0];}if(_d&&!store.getTiddler(_d)){return false;}var _e=function(e){if(!e){var e=window.event;}var _11=Popup.create(this);var _12=store.getTags();var _13=new Array();for(var i=0;i<_12.length;i++){_13.push(_12[i][0]);}if(_d){var _15=store.getTiddler(_d);_13=_15.tags.sort();}var _16=_6.tags.sort();var _17=function(_18,_19,_1a){var sp=createTiddlyElement(createTiddlyElement(_11,"li"),"span",null,"tagger");var _1c=createTiddlyButton(sp,_18,_1a+" '"+_19+"'",taggerOnToggle,"button","toggleButton");_1c.setAttribute("tiddler",_6.title);_1c.setAttribute("tag",_19);insertSpacer(sp);if(window.createTagButton_orig_mptw){createTagButton_orig_mptw(sp,_19)}else{createTagButton(sp,_19);}};createTiddlyElement(_11,"li",null,"listTitle",(_6.tags.length==0?_7.notags:_7.aretags));for(var t=0;t<_16.length;t++){_17("[x]",_16[t],"remove tag ");}createTiddlyElement(createTiddlyElement(_11,"li"),"hr");if(_b!="false"){createTiddlyElement(_11,"li",null,"listTitle",_7.toggletext);for(var i=0;i<_13.length;i++){if(!_6.tags.contains(_13[i])&&!_c.contains(_13[i])){_17("[ ]",_13[i],"add tag ");}}createTiddlyElement(createTiddlyElement(_11,"li"),"hr");}var _1f=createTiddlyButton(createTiddlyElement(_11,"li"),("Create new tag"),null,taggerOnToggle);_1f.setAttribute("tiddler",_6.title);if(_d){_1f.setAttribute("source",_d);}Popup.show(_11,false);e.cancelBubble=true;if(e.stopPropagation){e.stopPropagation();}return (false);};createTiddlyButton(_1,_9,_a,_e,"button","taggerDrpBtn");};window.taggerOnToggle=function(e){var tag=this.getAttribute("tag");var _22=this.getAttribute("tiddler");var _23=store.getTiddler(_22);if(!tag){var _24=prompt("Enter new tag:","");if(_24!=""&&_24!=null){var tag=_24;if(this.getAttribute("source")){var _26=store.getTiddler(this.getAttribute("source"));_26.tags.pushUnique(_24);}}else{return false;}}if(!_23||!_23.tags){store.saveTiddler(_22,_22,"",config.options.txtUserName,new Date(),tag);}else{if(_23.tags.find(tag)==null){_23.tags.push(tag);}else{if(!_24){_23.tags.splice(_23.tags.find(tag),1);}}store.saveTiddler(_23.title,_23.title,_23.text,_23.modifier,_23.modified,_23.tags);}story.refreshTiddler(_22,null,true);if(config.options.chkAutoSave){saveChanges();}return false;};setStylesheet(".tagger a.button {font-weight: bold;display:inline; padding:0px;}\n"+".tagger #toggleButton {padding-left:2px; padding-right:2px; margin-right:1px; font-size:110%;}\n"+"#nestedtagger {background:#2E5ADF; border: 1px solid #0331BF;}\n"+".popup .listTitle {color:#000;}\n"+"","TaggerStyles");window.lewcidTiddlerSwapTag=function(_27,_28,_29){for(var i=0;i<_27.tags.length;i++){if(_27.tags[i]==_28){_27.tags[i]=_29;return true;}}return false;};window.lewcidRenameTag=function(e){var tag=this.getAttribute("tag");var _2d=prompt("Rename tag '"+tag+"' to:",tag);if((_2d==tag)||(_2d==null)){return false;}if(store.tiddlerExists(_2d)){if(confirm(config.messages.overwriteWarning.format([_2d.toString()]))){story.closeTiddler(_2d,false,false);}else{return null;}}tagged=store.getTaggedTiddlers(tag);if(tagged.length!=0){for(var j=0;j<tagged.length;j++){lewcidTiddlerSwapTag(tagged[j],tag,_2d);}}if(store.tiddlerExists(tag)){store.saveTiddler(tag,_2d);}if(document.getElementById("tiddler"+tag)){var _2f=document.getElementById(story.idPrefix+tag);var _30=story.positionTiddler(_2f);var _31=document.getElementById(story.container);story.closeTiddler(tag,false,false);story.createTiddler(_31,_30,_2d,null);story.saveTiddler(_2d);}if(config.options.chkAutoSave){saveChanges();}return false;};window.onClickTag=function(e){if(!e){var e=window.event;}var _34=resolveTarget(e);var _35=(!isNested(_34));if((Popup.stack.length>1)&&(_35==true)){Popup.removeFrom(1);}else{if(Popup.stack.length>0&&_35==false){Popup.removeFrom(0);}}var _36=(_35==false)?"popup":"nestedtagger";var _37=createTiddlyElement(document.body,"ol",_36,"popup",null);Popup.stack.push({root:this,popup:_37});var tag=this.getAttribute("tag");var _39=this.getAttribute("tiddler");if(_37&&tag){var _3a=store.getTaggedTiddlers(tag);var _3b=[];var li,r;for(r=0;r<_3a.length;r++){if(_3a[r].title!=_39){_3b.push(_3a[r].title);}}var _3d=config.views.wikified.tag;if(_3b.length>0){var _3e=createTiddlyButton(createTiddlyElement(_37,"li"),_3d.openAllText.format([tag]),_3d.openAllTooltip,onClickTagOpenAll);_3e.setAttribute("tag",tag);createTiddlyElement(createTiddlyElement(_37,"li"),"hr");for(r=0;r<_3b.length;r++){createTiddlyLink(createTiddlyElement(_37,"li"),_3b[r],true);}}else{createTiddlyText(createTiddlyElement(_37,"li",null,"disabled"),_3d.popupNone.format([tag]));}createTiddlyElement(createTiddlyElement(_37,"li"),"hr");var h=createTiddlyLink(createTiddlyElement(_37,"li"),tag,false);createTiddlyText(h,_3d.openTag.format([tag]));createTiddlyElement(createTiddlyElement(_37,"li"),"hr");var _40=createTiddlyButton(createTiddlyElement(_37,"li"),("Rename tag '"+tag+"'"),null,lewcidRenameTag);_40.setAttribute("tag",tag);}Popup.show(_37,false);e.cancelBubble=true;if(e.stopPropagation){e.stopPropagation();}return (false);};if(!window.isNested){window.isNested=function(e){while(e!=null){var _42=document.getElementById("contentWrapper");if(_42==e){return true;}e=e.parentNode;}return false;};}config.shadowTiddlers.TaggerPluginDocumentation="The documentation is available [[here.|http://tw.lewcid.org/#TaggerPluginDocumentation]]";config.shadowTiddlers.TaggerPluginSource="The uncompressed source code is available [[here.|http://tw.lewcid.org/#TaggerPluginSource]]";
// %/
/***
|''Name:''|TagsTreePlugin|
|''Description:''|Displays tags hierachy as a tree of tagged tiddlers.<br>Can be used to create dynamic outline navigation.|
|''Version:''|1.0.1|
|''Date:''|Jan 04,2008|
|''Source:''|http://visualtw.ouvaton.org/VisualTW.html|
|''Author:''|Pascal Collin|
|''License:''|[[BSD open source license|License]]|
|''~CoreVersion:''|2.1.0|
|''Browser:''|Firefox 2.0; InternetExplorer 6.0|
!Demo
On the plugin [[homepage|http://visualtw.ouvaton.org/VisualTW.html]] :
*Try to tag some <<newTiddler>> with a tag displayed in the menu and edit MainMenu.
*Look at some tags like [[Plugins]] or [[menu]].
!Installation
#import the plugin,
#save and reload,
#optionally, edit TagsTreeStyleSheet.
! Usage
{{{<<tagsTree>>}}} macro accepts the following //optional// parameters.
|!#|!parameter|!description|!by default|
|1|{{{root}}}|Uses {{{root}}} tag as tree root|- In a //tiddler// content or template : uses the tiddler as root tag.<br>- In the //page// content or template (by ex MainMenu) : displays all untagged tags.|
|2|{{{excludeTag}}}|Excludes all such tagged tiddlers from the tree|Uses default excludeLists tag|
|3|{{{level}}}|Expands nodes until level {{{level}}}.<br>Value {{{0}}} hides expand/collapse buttons.|Nodes are collapsed on first level|
|4|{{{depth}}}|Hierachy depth|6 levels depth (H1 to H6 header styles)|
|5|{{{sortField}}}|Alternate sort field. By example : "index".|Sorts tags and tiddlers alphabetically (on their title)|
|6|{{{labelField}}}|Alertnate label field. By example : "label".|Displays tiddler's title|

!Useful addons
*[[FieldsEditorPlugin]] : //create//, //edit//, //view// and //delete// commands in toolbar <<toolbar fields>>.
*[[TaggerPlugin]] : Provides a drop down listing current tiddler tags, and allowing toggling of tags.
!Advanced Users
You can change the global defaults for TagsTreePlugin, like default {{{level}}} value or level styles, by editing or overriding the first config.macros.tagsTree attributes below.
!Code
***/
//{{{
config.macros.tagsTree = {
	expand : "+",
	collapse : "–",
	depth : 6,
	level : 1,
	sortField : "",	
	labelField : "",
	styles : ["h1","h2","h3","h4","h5","h6"],
	trees : {}
}

config.macros.tagsTree.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
	var root = params[0] ? params[0] : (tiddler ? tiddler.title : null);
	var excludeTag = params[1] ? params[1] : "excludeTagsTree";
	var level = params[2] ? params[2] : config.macros.tagsTree.level;
	var depth = params[3] ? params[3] : config.macros.tagsTree.depth;
	var sortField = params[4] ? params[4] : config.macros.tagsTree.sortField;
	var labelField = params[5] ? params[5] : config.macros.tagsTree.labelField;
	var showButtons = (level>0);
	var id = config.macros.tagsTree.getId(place);
	if (config.macros.tagsTree.trees[id]==undefined) config.macros.tagsTree.trees[id]={};
	config.macros.tagsTree.createSubTree(place,id,root,excludeTag,[],level>0 ? level : 1,depth, sortField, labelField,showButtons);
}

config.macros.tagsTree.createSubTree = function(place, id, root, excludeTag, ancestors, level, depth, sortField, labelField,showButtons){
	var childNodes = root ? this.getChildNodes(root, ancestors) : this.getRootTags(excludeTag);
	var isOpen = (level>0) || (!showButtons);
	if (root && this.trees[id][root]!=undefined) isOpen = this.trees[id][root]; 
	if (root && ancestors.length) {
		var t = store.getTiddler(root);
		if (childNodes.length && depth>0) {
			var wrapper = createTiddlyElement(place , this.styles[Math.min(Math.max(ancestors.length,1),6)-1],null,"branch");
			if (showButtons) {
				b = createTiddlyButton(wrapper, isOpen ? config.macros.tagsTree.collapse : config.macros.tagsTree.expand, null, config.macros.tagsTree.onClick);
				b.setAttribute("treeId",id);
				b.setAttribute("tiddler",root);					
			}
			createTiddlyText(createTiddlyLink(wrapper, root),t&&labelField ? t.fields[labelField] ? t.fields[labelField] : root : root);
		}
		else 
			createTiddlyText(createTiddlyLink(place, root,false,"leaf"),t&&labelField ? t.fields[labelField] ? t.fields[labelField] : root : root);
	}
	if (childNodes.length && depth) {
		var d = createTiddlyElement(place,"div",null,"subtree");
		d.style.display= isOpen ? "block" : "none";
		if (sortField)
			childNodes.sort(function(a, b){
				var fa=a.fields[sortField];
				var fb=b.fields[sortField];
				return (fa==undefined && fb==undefined) ? a.title < b.title ? -1 : a.title > b.title ? 1 : 0 : (fa==undefined && fb!=undefined) ? 1 :(fa!=undefined && fb==undefined) ? -1 : fa < fb ? -1 : fa > fb ? 1 : 0;
			})
		for (var cpt=0; cpt<childNodes.length; cpt++)
			this.createSubTree(d, id, childNodes[cpt].title, excludeTag, ancestors.concat(root), level-1, depth-1, sortField, labelField, showButtons);	
	}	
}

config.macros.tagsTree.onClick = function(e){
	var id = this.getAttribute("treeId");
	var tiddler = this.getAttribute("tiddler");	
	var n = this.parentNode.nextSibling;
	var isOpen = n.style.display != "none";
	if(config.options.chkAnimate && anim && typeof Slider == "function")
		anim.startAnimating(new Slider(n,!isOpen,null,"none"));
	else
		n.style.display = isOpen ? "none" : "block";
	this.firstChild.nodeValue = isOpen ? config.macros.tagsTree.expand : config.macros.tagsTree.collapse;
	config.macros.tagsTree.trees[id][tiddler]=!isOpen;
	return false;
}

config.macros.tagsTree.getChildNodes = function(root ,ancestors){
	var childs = store.getTaggedTiddlers(root);
	var result = new Array();
	for (var cpt=0; cpt<childs.length; cpt++)
		if (childs[cpt].title!=root && ancestors.indexOf(childs[cpt].title)==-1) result.push(childs[cpt]);
	return result;
}

config.macros.tagsTree.getRootTags = function(excludeTag){
	var tags = store.getTags(excludeTag);
	tags.sort(function(a,b) {return a[0].toLowerCase() < b[0].toLowerCase() ? -1 : (a[0].toLowerCase() == b[0].toLowerCase() ? 0 : +1);});
	var result = new Array();
	for (var cpt=0; cpt<tags.length; cpt++) {
		var t = store.getTiddler(tags[cpt][0]);
		if (!t || t.tags.length==0) result.push(t ? t : {title:tags[cpt][0],fields:{}});
	}
	return result;
}

config.macros.tagsTree.getId = function(element){
	while (!element.id && element.parentNode) element=element.parentNode;
	return element.id ? element.id : "<html>";
}

config.shadowTiddlers.TagsTreeStyleSheet = "/*{{{*/\n";
config.shadowTiddlers.TagsTreeStyleSheet +=".leaf, .subtree {display:block; margin-left : 0.5em}\n";
config.shadowTiddlers.TagsTreeStyleSheet +=".subtree {margin-bottom:0.5em}\n";
config.shadowTiddlers.TagsTreeStyleSheet +="#mainMenu {text-align:left}\n";
config.shadowTiddlers.TagsTreeStyleSheet +=".branch .button {border:1px solid #DDD; color:#AAA;font-size:9px;padding:0 2px;margin-right:0.3em;vertical-align:middle;text-align:center;}\n";
config.shadowTiddlers.TagsTreeStyleSheet +="/*}}}*/";

store.addNotification("TagsTreeStyleSheet", refreshStyles); 

config.shadowTiddlers.MainMenu="<<tagsTree>>"

config.shadowTiddlers.PageTemplate = config.shadowTiddlers.PageTemplate.replace(/id='mainMenu' refresh='content' /,"id='mainMenu' refresh='content' force='true' ")

//}}}
/*{{{*/
.leaf, .subtree {display:block}

/* 設定 Tree 第一層的 left margin */ 
#mainMenu>.subtree {margin-left:0em}

.leaf {margin-left:0.2em; margin-bottom:0.2em; color:navy;}
.subtree {margin-left:0.8em;}

.branch .button {
   border:1px solid #DDD; color:#999;
   font-size:10px;padding:0 4px;
   margin-right:0.5em;
   vertical-align:middle;text-align:center;
}

/*}}}*/
/***
|''Name:''|TiddlersBarPlugin|
|''Description:''|A bar to switch between tiddlers through tabs (like browser tabs bar).|
|''Version:''|1.2.5|
|''Date:''|Jan 18,2008|
|''Source:''|http://visualtw.ouvaton.org/VisualTW.html|
|''Author:''|Pascal Collin|
|''License:''|[[BSD open source license|License]]|
|''~CoreVersion:''|2.1.0|
|''Browser:''|Firefox 2.0; InternetExplorer 6.0, others|
!Tips
*Doubleclick on the tiddlers bar (where there is no tab) create a new tiddler.
*Tabs include a button to close {{{x}}} or save {{{!}}} their tiddler.
*By default, click on the current tab close all others tiddlers.
!Configuration options 
<<option chkDisableTabsBar>> Disable the tabs bar (to print, by example).
<<option chkHideTabsBarWhenSingleTab >> Automatically hide the tabs bar when only one tiddler is displayed. 
<<option txtSelectedTiddlerTabButton>> ''selected'' tab command button.
<<option txtPreviousTabKey>> previous tab access key.
<<option txtNextTabKey>> next tab access key.
!Code
***/
//{{{
config.options.chkDisableTabsBar = config.options.chkDisableTabsBar ? config.options.chkDisableTabsBar : false;
config.options.chkHideTabsBarWhenSingleTab  = config.options.chkHideTabsBarWhenSingleTab  ? config.options.chkHideTabsBarWhenSingleTab  : false;
config.options.txtSelectedTiddlerTabButton = config.options.txtSelectedTiddlerTabButton ? config.options.txtSelectedTiddlerTabButton : "closeOthers";
config.options.txtPreviousTabKey = config.options.txtPreviousTabKey ? config.options.txtPreviousTabKey : "";
config.options.txtNextTabKey = config.options.txtNextTabKey ? config.options.txtNextTabKey : "";
config.macros.tiddlersBar = {
	tooltip : "see ",
	tooltipClose : "click here to close this tab",
	tooltipSave : "click here to save this tab",
	promptRename : "Enter tiddler new name",
	currentTiddler : "",
	previousState : false,
	previousKey : config.options.txtPreviousTabKey,
	nextKey : config.options.txtNextTabKey,	
	tabsAnimationSource : null, //use document.getElementById("tiddlerDisplay") if you need animation on tab switching.
	handler: function(place,macroName,params) {
		var previous = null;
		if (config.macros.tiddlersBar.isShown())
			story.forEachTiddler(function(title,e){
				if (title==config.macros.tiddlersBar.currentTiddler){
					var d = createTiddlyElement(null,"span",null,"tab tabSelected");
					config.macros.tiddlersBar.createActiveTabButton(d,title);
					if (previous && config.macros.tiddlersBar.previousKey) previous.setAttribute("accessKey",config.macros.tiddlersBar.nextKey);
					previous = "active";
				}
				else {
					var d = createTiddlyElement(place,"span",null,"tab tabUnselected");
					var btn = createTiddlyButton(d,title,config.macros.tiddlersBar.tooltip + title,config.macros.tiddlersBar.onSelectTab);
					btn.setAttribute("tiddler", title);
					if (previous=="active" && config.macros.tiddlersBar.nextKey) btn.setAttribute("accessKey",config.macros.tiddlersBar.previousKey);
					previous=btn;
				}
				var isDirty =story.isDirty(title);
				var c = createTiddlyButton(d,isDirty ?"!":"x",isDirty?config.macros.tiddlersBar.tooltipSave:config.macros.tiddlersBar.tooltipClose, isDirty ? config.macros.tiddlersBar.onTabSave : config.macros.tiddlersBar.onTabClose,"tabButton");
				c.setAttribute("tiddler", title);
				if (place.childNodes) {
					place.insertBefore(document.createTextNode(" "),place.firstChild); // to allow break line here when many tiddlers are open
					place.insertBefore(d,place.firstChild); 
				}
				else place.appendChild(d);
			})
	}, 
	refresh: function(place,params){
		removeChildren(place);
		config.macros.tiddlersBar.handler(place,"tiddlersBar",params);
		if (config.macros.tiddlersBar.previousState!=config.macros.tiddlersBar.isShown()) {
			story.refreshAllTiddlers();
			if (config.macros.tiddlersBar.previousState) story.forEachTiddler(function(t,e){e.style.display="";});
			config.macros.tiddlersBar.previousState = !config.macros.tiddlersBar.previousState;
		}
	},
	isShown : function(){
		if (config.options.chkDisableTabsBar) return false;
		if (!config.options.chkHideTabsBarWhenSingleTab) return true;
		var cpt=0;
		story.forEachTiddler(function(){cpt++});
		return (cpt>1);
	},
	selectNextTab : function(){  //used when the current tab is closed (to select another tab)
		var previous="";
		story.forEachTiddler(function(title){
			if (!config.macros.tiddlersBar.currentTiddler) {
				story.displayTiddler(null,title);
				return;
			}
			if (title==config.macros.tiddlersBar.currentTiddler) {
				if (previous) {
					story.displayTiddler(null,previous);
					return;
				}
				else config.macros.tiddlersBar.currentTiddler=""; 	// so next tab will be selected
			}
			else previous=title;
			});		
	},
	onSelectTab : function(e){
		var t = this.getAttribute("tiddler");
		if (t) story.displayTiddler(null,t);
		return false;
	},
	onTabClose : function(e){
		var t = this.getAttribute("tiddler");
		if (t) {
			if(story.hasChanges(t) && !readOnly) {
				if(!confirm(config.commands.cancelTiddler.warning.format([t])))
				return false;
			}
			story.closeTiddler(t);
		}
		return false;
	},
	onTabSave : function(e) {
		var t = this.getAttribute("tiddler");
		if (!e) e=window.event;
		if (t) config.commands.saveTiddler.handler(e,null,t);
		return false;
	},
	onSelectedTabButtonClick : function(event,src,title) {
		var t = this.getAttribute("tiddler");
		if (!event) event=window.event;
		if (t && config.options.txtSelectedTiddlerTabButton && config.commands[config.options.txtSelectedTiddlerTabButton])
			config.commands[config.options.txtSelectedTiddlerTabButton].handler(event, src, t);
		return false;
	},
	onTiddlersBarAction: function(event) {
		var source = event.target ? event.target.id : event.srcElement.id; // FF uses target and IE uses srcElement;
		if (source=="tiddlersBar") story.displayTiddler(null,'New Tiddler',DEFAULT_EDIT_TEMPLATE,false,null,null);
	},
	createActiveTabButton : function(place,title) {
		if (config.options.txtSelectedTiddlerTabButton && config.commands[config.options.txtSelectedTiddlerTabButton]) {
			var btn = createTiddlyButton(place, title, config.commands[config.options.txtSelectedTiddlerTabButton].tooltip ,config.macros.tiddlersBar.onSelectedTabButtonClick);
			btn.setAttribute("tiddler", title);
		}
		else
			createTiddlyText(place,title);
	}
}

story.coreCloseTiddler = story.coreCloseTiddler? story.coreCloseTiddler : story.closeTiddler;
story.coreDisplayTiddler = story.coreDisplayTiddler ? story.coreDisplayTiddler : story.displayTiddler;

story.closeTiddler = function(title,animate,unused) {
	if (title==config.macros.tiddlersBar.currentTiddler)
		config.macros.tiddlersBar.selectNextTab();
	story.coreCloseTiddler(title,false,unused); //disable animation to get it closed before calling tiddlersBar.refresh
	var e=document.getElementById("tiddlersBar");
	if (e) config.macros.tiddlersBar.refresh(e,null);
}

story.displayTiddler = function(srcElement,tiddler,template,animate,unused,customFields,toggle){
	story.coreDisplayTiddler(config.macros.tiddlersBar.tabsAnimationSource,tiddler,template,animate,unused,customFields,toggle);
	var title = (tiddler instanceof Tiddler)? tiddler.title : tiddler;  
	if (config.macros.tiddlersBar.isShown()) {
		story.forEachTiddler(function(t,e){
			if (t!=title) e.style.display="none";
			else e.style.display="";
		})
		config.macros.tiddlersBar.currentTiddler=title;
	}
	var e=document.getElementById("tiddlersBar");
	if (e) config.macros.tiddlersBar.refresh(e,null);
}

var coreRefreshPageTemplate = coreRefreshPageTemplate ? coreRefreshPageTemplate : refreshPageTemplate;
refreshPageTemplate = function(title) {
	coreRefreshPageTemplate(title);
	if (config.macros.tiddlersBar) config.macros.tiddlersBar.refresh(document.getElementById("tiddlersBar"));
}

//ensureVisible=function (e) {return 0} //disable bottom scrolling (not useful now)

config.shadowTiddlers.StyleSheetTiddlersBar = "/*{{{*/\n";
config.shadowTiddlers.StyleSheetTiddlersBar += "#tiddlersBar .button {border:0}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += "#tiddlersBar .tab {white-space:nowrap}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += "#tiddlersBar {padding : 1em 0.5em 2px 0.5em}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += ".tabUnselected .tabButton, .tabSelected .tabButton {padding : 0 2px 0 2px; margin: 0 0 0 4px;}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += ".tiddler, .tabContents {border:1px [[ColorPalette::TertiaryPale]] solid;}\n";
config.shadowTiddlers.StyleSheetTiddlersBar +="/*}}}*/";
store.addNotification("StyleSheetTiddlersBar", refreshStyles);

config.refreshers.none = function(){return true;}
config.shadowTiddlers.PageTemplate=config.shadowTiddlers.PageTemplate.replace(/<div id='tiddlerDisplay'><\/div>/m,"<div id='tiddlersBar' refresh='none' ondblclick='config.macros.tiddlersBar.onTiddlersBarAction(event)'></div>\n<div id='tiddlerDisplay'></div>");

//}}}
本文網址 : http://www.zdnet.com.tw/news/software/0,2000085678,20145247,00.htm

ZDNet記者郭立偉/台北報導 2010/04/27 18:44:04

Ubuntu 10.4作業系統週四才會開始提供下載,但開發人員已經開始籌畫下一版要加入什麼功能了。

Canonical台灣區業務經理黃鴻文今(27)日透露,今(10)年10月將發表的Ubuntu 10.10,雖然尚未決定要加入哪些功能,但就目前聽到客戶(品牌與代工廠商)要求的聲音,提供類似iPad的平板電腦支援將是可能方向,也就是會支援螢幕的多點觸控操作以及其他相關功能。

黃鴻文並表示,對於平板應用來說軟體內容是很重要的一環,Ubuntu雖然已經有Software Center供用戶下載、安裝軟體,但尚無收費機制。在10.4版已有可刷卡付費下載音樂的Ubuntu one music store,可知提供收費機制會是可行的方向, 將考慮在10.10版加入,藉此吸引更多開發者來提供軟體。

再者,Ubuntu目前尚無像手機作業系統那樣的SDK(Software Development Kit,軟體開發套件)可幫助程式設計者快速開發軟體,這也是未來要解決的問題。

事實上不用等到10月之後,現在就已經有Ubuntu平板了。日本廠商夏普(Sharp)這個月推出的PC-T1,就是一款搭載Ubuntu 9.04版的平板產品(或者叫它MID也行),提供5吋觸控螢幕,不過,還只有單點觸控就是了。

Ubuntu作業系統是固定每6個月更新一次版本(每年4月、10月各一次),4月剛發表的是Ubuntu 10.4 LTS(Long Term Support,長期支援版),代號Lucid Lynx (清醒的猞猁)。而10月會釋出的10.10 版代號為Maverick Meerkat(標新立異的狐獴),似乎正暗示著新版將有更多讓人驚奇的創新。
本文網址 : http://www.ithome.com.tw/itadm/article.php?c=64133

下一版Ubuntu 11.04的圖形使用者介面將由目前的GNOME改成10.10小筆電版所用的Unity介面。

根據外電報導,Ubuntu創辦人Mark Shuttleworth在周一(10/25)舉辦的Ubuntu開發者高峰會中宣佈,下一版Ubuntu 11.04的圖形使用者介面將由目前的GNOME改成10.10小筆電版所用的Unity介面。Mark Shuttleworth宣稱是因為使用者希望Unity介面成為Ubuntu標準介面才會如此決定。

不過使用Unity介面的前提是電腦能支援3D繪圖,如果電腦無法支援3D圖形功能,Ubuntu將會使用GNOME作為圖形介面。當然,在安裝時使用者仍可以自定選用GNOME為使用者介面。而針對GNOME及KDE所寫的程式亦可在Unity介面下執行。Mark Shuttleworth表示,兩者都是GNOME的外殼,只是外觀不同而已,Ubuntu不會拋棄GNOME。

GNOME 3.0將採用的GNOME Shell與Unity均使用MeeGO延伸出來的圖形程式庫Clutter來開發,因此具有一定的相容程度。

不過Mark Shuttleworth在國外媒體訪問中承認,仍須開發人員投入大量的工作之後才能把Unity介面移植到桌上型電腦。除了要針對桌上型電腦最佳化之外,由於Mark Shuttleworth認為將來的筆電都將整合觸控的功能,因此最新版的Ubuntu將加入多點觸控的功能uTouch到Unity介面。(編譯/沈經) 
ZDNet新聞專區:Stephen Shankland  2008/10/28 12:53:02

Canonical執行長Mark Shuttleworth 周一表示,最新的Ubuntu版Linux預定本周四推出,但該公司要轉虧為盈還尚待時日。

Ubuntu 8.10 (代號「Intrepid Ibex」)是Canonical最新的Linux版本,適用於桌上型電腦以及伺服器。新增功能包括:支援3G無線數據機、設定加密與密碼保護的私人目錄 (private directory)、設立訪客帳號(guest account)以協助臨時需要用電腦的使用者,以及內建擷取自BBC的內容。

在伺服器方面,8.10版包括加強支援Xen虛擬化、用來管理並部署Ubuntu的Landscape控制台(console)、用來建置客製化虛擬機器的軟體,以及支援軟體型RAID以保護儲存系統上的資料。

和主要競爭對手不同,Ubuntu不論是玩家版或有服務支援的版本,都可免費取得。近年來,Ubuntu在攻佔市場方面大有斬獲,讓Red Hat和Novell的Suse Linux流失了一些市占率。不過,目前為止,Ubuntu尚未能為Canonical公司賺錢。

但執行長Shuttleworth對Canonical有信心,更有耐心。Verisign是他上一個成立的公司,出售Verisign讓他變成富翁。

Shuttleworth在周一的電話會議中說:「我不反對再繼續投資三、五年。我有耐心。我認為,這波不景氣對Canonical有利.Canonical尚未能帶來正現金流量,但我們提供的服務對需要看緊預算的人來說,是非常有效益的。」

對Shuttleworth而言,獲利是遲早的事他寧可投資該公司認定為重要的領域,而不願為了快速賺錢而揠苗助長。「如果必要的話,我們或許兩年後就能開始賺錢,只要專注於核心事業如伺服器版本即可。」

該公司的業務主要靠銷售支援,服務對象包括Linux軟體的用戶,或需要專業協助建置Linux系統的公司。在他看來,銷售單機桌上型PC版的Linux,獲利展望並不光明。

Shuttleworth說:「我認為那不可能賺很多錢,甚至可能賺不了錢。我們不想靠銷售桌上版賺錢,而是強迫自己關注服務導向式的商業模式。我相信,就這一行而言,這才是正確的商業模式。」

目前最新的已發布Ubuntu是8.4版(代號「Hardy Heron」),將成為最後一個Canonical提供長期支援的版本,伺服器版支援期限為五年,桌上型版為三年。「Intrepid Ibex」是普通發布版,提供18個月的支援。(唐慧文/譯) 

Ubuntu 創辦人Mark Shuttleworth 上週五(20日)宣布,Ubuntu 9.10 將以 Karmic Koala 為代號。一如往常,Ubuntu Linux將分成兩部分:桌面版和伺服器版。桌面版的主要目標是「第一印象」,Shuttleworth 暗示「開機過程將令人驚豔」。他也承諾Ubuntu 的外觀設計將有顯著改變。

他說:「桌面版將充滿設計師穿鑿的痕跡,我們已開始認真地進行新外觀的製作。Brown 讓我們很滿意,但 Koala 會考慮其他選擇。」

我相信其他人也會以同樣認真的態度,檢視桌面版的設計。但 Shuttleworth 口中的伺服器版功能,則讓雲端運算社群更感興趣。看來 Karmic Koala 伺服器版的主要工作,將與雲端運算相關。以下是 Shuttleworth 這部分聲明的完整內容:

「一隻聰明的無尾熊(Koala)即使身在雲霧中,也看得到整片樹林。Ubuntu 要利用 Amazon EC2 的 APIs,將自由軟體置於雲端運算的前鋒,讓任何人都能使用完全開放的工具,輕鬆設立他們自己的雲端。我們目前正在測試 Ubuntu AMI 在Amazon EC2 上執行。在 Karmic 期間,我們要簡化應用軟體在雲端的佈署,利用即可用的設備,或快速收集的訂製影像。Ubuntu-vmbuilder 可用來輕鬆製作訂製的 AMI,但標準影像檔案集,可讓 EC2 上從事類似工作的人,更容易協調合作。讓 Amazon 叢林變得更容易通過,對 Ubuntu 而言不是更恰當嗎?

如果你要自行建構一個 EC2 形式雲端該如何?無尾熊最愛的是尤加利葉。UCSB 的 Eucalyptus(尤加利樹)計畫,能讓你在自己的硬體上、為自己的資料中心製作一個 EC-2 形式雲端。Eucalyptus 已加入整體的大計劃,在 Karmic 期間,我們將讓這些雲端飛舞,根據各位的需求,動態地增減資源配置。聰明的無尾熊知道,保存精力最好的方式就是睡覺,現在就連伺服器都可以中止和重啟,你可以想像,我們能建構一個在午睡時間耗能降到近乎零,有工作再醒來的雲端運算設施。」

如果你看不懂,重點如下:

1. Ubuntu 伺服器版的目標,是以完全開原碼的軟體,推動雲端運算。

2. 針對那些有意管理雲端的人,Ubuntu 將包含利用Amazon APIs 優勢的工具。(我希望 GoGrid APIs 也在考慮之列,因為這是多個 Amazon 競爭者採用的介面。)

3. Canonical 將根據 Karmic Koala 製作標準的 Amazon Machine Images,基本上是為 Amazon 社群製作相當於「標準構造」的「即可用」裝備。

4. 不想專用 Amazon?你寧願用自己的基礎設施建構一個雲端,而捨棄好用的公共雲端?從 Karmic 的前身 Jaunty Jaguar Jackalope(程式碼即將凍結)開始,UC Santa Barbara 的開原碼計畫 Eucalyptus,將納入每一個版本。

我確定 Canonical 現任的軟體服務經理 Simon Wardley,對這個方向有很大的影響。他對開原碼標準在雲端運算領域的長期投入,讓這些工具的選擇顯得十分合理。未來幾個月內,Koala 包含的平台極可能改變,但 Shuttleworth、Wardley 和 Ubuntu社群信奉的開放軟體哲學,將主導他們的選擇。

這對雲端運算的未來有多重要仍待觀察,目前已有其他開原碼計畫含有「內建的」Amazon 影像(不只是RedHat),而Eucalyptus 是一個研究計畫,需要進一步製作,才能發揮生產用途。

在我眼中,Ubuntu 團隊就像是 Linux 的蘋果,極可能改變整個局勢,但不是透過基礎建設本身,而是他們以建構和管理雲端所創造的使用者經驗。我迫不及待。

ZDNet新聞專區:Stephen Shankland  2009/12/18 13:07:04

支持Ubuntu Linux的Canonical公司調整高階人事,創辦人Mark Shuttleworth將在明年3月1日前,把執行長的職位交棒給現任營運長Jane Silber。

Shuttleworth將持續留在公司,督導Canonical的桌上Linux產品、雲端運算計畫以及攸關公司業務的合作夥伴會議。Silber將投入更多時間,關注Canonical的商用產品。

當年Shuttleworth創立Ubuntu和Canonical,挑戰Red Hat與Novell的Suse Linux,後兩者都分成免費的版本,以及不同的商用版。但對Ubuntu而言,兩種版本都一樣,意味想得到經過測試與驗證的產品,不一定得花錢買。不過,Canonical提供付費會員支援服務。

目前Canonical除了Linux伺服器支援業務之外,還有兩大營收來源:與小筆電廠商的作業系統技術合作關係(包括最近與Google的 Chrome OS合作關係),以及銷售對Ubuntu雲端運算技術的支援。後者是與Eucalyptus Systems聯手研發而成。

Shuttleworth在1999年把他創辦的Thawte網際網路諮詢公司賣給Verisign,並以這筆錢創立Canonical。他對公司的財務採取長程觀點:「我們尚未賺錢,但我相信,我們的方向正確。」

Canonical已成立五年,目前員工超過300人。

Canonical每六個月發布新版的Ubuntu,最新的一版是9.10版,代號是"Karmic Koala"。 代號"Lucid Lynx"的10.4版預定在明年4月推出,將是附帶長期支援(long-term support,LTS)的版本。Canonical每兩年推出新的LTS版本。(唐慧文譯)
ZDNET新聞專區: 蔡宜秀 2009/09/10 19:13:01

Ubuntu 號稱要把第一次獻給台灣。

Linux 作業系統 Ubuntu 的商業贊助商 Canonical 表示,將在 9 月15日於台北維多利亞酒店舉辦 Ubuntu全球史上第一次,也是台灣首次的 Ubuntu 硬體高峰會(Ubuntu Hardware Summit)。

Canonical 台灣業務經理黃鴻文今(10)日表示,該公司為與硬體工程師進行更密切的溝通、協助其開發專屬 Ubuntu 等 Linux 作業系統的硬體裝置驅動程式,決定選在台灣舉行這次的硬體高峰會。

他解釋,該公司之所以會在台灣試辦該活動,與全球有 80% 的資通訊硬體產品是由台灣廠商研發、產製有關。

「若是市場反應不錯,公司也將長期舉辦 Ubuntu 硬體高峰會,與硬體夥伴商亦相關的規格制定等工作。」他說。

Canonical 表示,由於該公司是第一次舉辦 Ubuntu 硬體高峰會,因此,這一次的活動講師將由 Canonical 國內外同仁擔綱,以後才有可能進一步邀請廣達、鴻海、緯創、技嘉、仁寶與和碩等台灣硬體合作夥伴分享經驗。

Ubuntu先前已經舉辦過多次軟體開發者大會(Ubuntu Developer Summit),但在今年Ubuntu則特別針對硬體開發者主辦第一次Ubuntu硬體高峰會。
如果是在UTF-8的環境下的話,可以用fbterm來顯示中文
不過我是用單純的ubuntu 10.04,server版應該類似吧^^
{{{
apt-get install fbterm
}}}
不過fbterm需要用到framebuffer(/dev/fb0, vga16fb好像例外^^")
所以需使用 VESA來顯示console,
我使用的是GRUB2(GRUB-PC),是這樣加參數的
{{{
GRUB_CMDLINE_LINUX=""
改為
GRUB_CMDLINE_LINUX="vga=0x31B video=vesafb:mtrr:2,ywrap"
}}}

0x31B 代表的解析度是:1280x1024 16M色,可參考
http://www.mjmwired.net/kernel/Documentation/fb/vesafb.txt

需要update-grub重新產生grub-pc的開機選單,
重開機如果想反悔,不用這剛加上去的參數,可以按e編輯,去掉那串字即可
然後Ctrl-x開機


多載入兩個模組進initramfs
編輯/etc/initramfs-tools/modules
多加這兩行
{{{
vesafb
fbcon
}}}
http://www.mjmwired.net/kernel/Documentation/fb/vesafb.txt
http://www.mjmwired.net/kernel/Documentation/fb/fbcon.txt

存檔後執行 update-initramfs -u -v
重新產生ramfs的東西

更改/etc/modprobe.d /blacklist-framebuffer.conf
這裡ubuntu有設模組的黑名單
{{{
# Framebuffer drivers are generally buggy and poorly-supported, and cause
# suspend failures, kernel panics and general mayhem. For this reason we
# never load them automatically.
....
....
blacklist sisfb
blacklist sstfb
blacklist tdfxfb
blacklist tridentfb
#blacklist vesafb
blacklist vfb
blacklist viafb
blacklist vt8623fb
}}}
如上所示,註解blacklist vesafb,不然vesafb可能無法載進使用,會看到一片黑茫茫
雖然系統還活者,但變得只能Ctrl+Alt+Del(init 6)重開機調參數


以上都成功後
就可以用

fbterm -s 16

在console 下顯示16字的中文檔名了
<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler > fields syncing permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>

<!--
<div class='tagging' macro='tagging'></div>
-->
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
網址 : http://joliclic.free.fr/html/object-tag/en/ 

A lot of people insert medias in their web page with the non-standard <embed> tag. But there is a standard tag for this insertion kind, <object> . Effectively this is not immediate to use it manner cross-browsers, but we'll see that there are some techniques for that practically all the browsers be able to understand the code.

The HTML 4.01 specification introduce the <object> element :

    ...HTML 4 introduces the OBJECT element, which offers an all-purpose solution to generic object inclusion. The OBJECT element allows HTML authors to specify everything required by an object for its presentation by a user agent: source code, initial values, and run-time data. In this specification, the term "object" is used to describe the things that people want to place in HTML documents; other commonly used terms for these things are: applets, plug-ins, media handlers, etc.

This element is designed to include any sort of document. We specify which sort with the type attribute indicating the mime type, and the source of the document with the data attribute indicating his URI.

If the browser, or one of his plugin, can interpret this document, it does it, otherwise the nested content of the object is displayed.
Any HTML code can be inserted as a alternative content, for example a link to the document or an image instead an animation. It can be also another alternative object, we talk about "nested object".

For a lot of type of document, that's all !

''examples :''

embed a HTML document
{{{
<object data="data/test.html" type="text/html" width="300" height="200">
  alt : <a href="data/test.html">test.html</a>
</object>
}}}

embed a pdf document
{{{
<object data="data/test.pdf" type="application/pdf" width="300" height="200">
  alt : <a href="data/test.pdf">test.pdf</a>
</object>
}}}

You can specify some parameters related to the document with the param tag. IE sometimes needs a src parameter to understand the location.

embed a wav document
{{{
<object type="audio/x-wav" data="data/test.wav" width="200" height="20">
  <param name="src" value="data/test.wav">
  <param name="autoplay" value="false">
  <param name="autoStart" value="0">
  alt : <a href="data/test.wav">test.wav</a>
</object>
}}}
The parameters autoplay is understandable by ~QuickTime, autoStart by Windows media Player and Real Audio.

!More complicated cases

For some types, like ~QuickTime document, IE needs a non-standard value to the valid classid attribute, an identifier to load an associated activeX.

an only IE insertion of a ~QuickTime document
{{{
<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
        width="320" height="240">
  <param name="src" value="data/test.mov" >
  alt : <a href="data/test.mov">test.mov</a>
</object>
}}}

We 're going to nest another object as an alternative content, for the other browsers that use the standard formulation :

nested objects
{{{
<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
        width="320" height="240">
  <param name="src" value="data/test.mov" >
  <param name="controller" value="true" >
  <param name="autoplay" value="false">

  <object type="video/quicktime" data="data/test.mov" width="320" height="240">
    <param name="controller" value="true" >
    <param name="autoplay" value="false">
   alt : <a href="data/test.mov">test.mov</a>
  </object>
</object>
}}}

It works, but unfortunately IE has a bug, it displays a blank zone for the second object.
This bug is resolved in ~IE7, but for older versions, we must hide this second object. We have two techniques to do it, the IE specific conditional comments, or by CSS.

Hide the nested object with IE conditional comments

~IE5 introduce the conditional comments, that is very helpful to compensate IE bugs. This method isn't understandable by earlier versions of IE, but fortunately they are almost not used.

We can write two objects, one specially for IE, and another for the standards respectful browsers :
{{{
<!--[if IE]>
<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
        width="320" height="240">
  <param name="src" value="data/test.mov" >
  <param name="controller" value="true" >
  <param name="autoplay" value="false">
</object>
<![endif]-->

<!--[if !IE]> <!-->
<object type="video/quicktime" data="data/test.mov" width="320" height="240">
  <param name="controller" value="true" >
  <param name="autoplay" value="false">
  alt : <a href="data/test.mov">test.mov</a>
</object>
<!--<![endif]-->
}}}

But as ~IE7 corrects this bug, I prefer to use them with nested objects :
{{{
<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
        width="320" height="240">
  <param name="src" value="data/test.mov" >
  <param name="controller" value="true" >
  <param name="autoplay" value="false">

  <!--[if gte IE 7]> <!-->
  <object type="video/quicktime" data="data/test.mov" width="320" height="240">
    <param name="controller" value="true" >
    <param name="autoplay" value="false">
   alt : <a href="data/test.mov">test.mov</a>
  </object>
  <!--<![endif]-->
  <!--[if lt IE 7]>
   alt : <a href="data/test.mov">test.mov</a>
  <![endif]-->
</object>
}}}

Hide the nested object with CSS

The other solution is to use some CSS hacks to hide the nested object. We must use a hack to create rules applied only by IE to hide the object, then another to render visible it again by IE Mac.

special class for IE (place it in a style tag on the head of the HTML document, or in a separate stylesheet)
{{{
/* hides the second object from all versions of IE */

* html object.hiddenObjectForIE { display: none; }

/* display the second object only for IE5 Mac */

/* IE Mac \*//*/
* html object.hiddenObjectForIE { display: inline; }
/**/
}}}

and apply this style to the nested object
{{{
<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
        width="320" height="240">
  <param name="src" value="data/test.mov" >
  <param name="controller" value="true" >
  <param name="autoplay" value="false">

  <object type="video/quicktime" data="data/test.mov"
         width="320" height="240"
         class="hiddenObjectForIE">
    <param name="controller" value="true" >
    <param name="autoplay" value="false">
   alt : <a href="data/test.mov">test.mov</a>
  </object>
</object>
}}}

This technic have some annoyances with java (and perhaps some other), a security alert is displayed on loading, and the alternative content of the nested object is also displayed.
網址 : http://www.ithome.com.tw/itadm/article.php?c=75150

微軟Windows Server 2012即將在9月上市,並公布了4種版本的美國售價,臺灣售價則將於9月1日公布

微軟在7月9日宣布全新作業系統Windows Server 2012確定將在9月上市,並已預先公布了美國官方售價。Windows Server 2012共分成4個版本:分別是Datacenter、Standard、Essentials,以及Foundation。而其中Foundation版本僅提供OEM廠商使用。

Windows Server 2012有4種授權版本選擇
首先,Datacenter版本為完整旗艦版,主要針對執行高度虛擬化以及混合雲的企業用戶,可以用來建置大量虛擬化服務,可安裝的虛擬機器授權數量沒有限制,售價為4,809美元,計價方式為依照使用者處理器數量及用戶端存取授權數計價。

其次,Standard版本則針對服務密度較低,或是不建置虛擬化的商業用戶,提供完整功能,但虛擬機器安裝授權數有限制,僅提供2臺虛擬機器的授權,售價為882美元,計價方式亦為依照處理器數量及用戶端存取授權數計價。

最後一個企業可以選擇的版本是Essentials版本,鎖定小型企業用戶,具有基本介面以及基礎雲端服務,不提供虛擬化平臺的使用授權。售價425美元,使用者帳戶數量限制為25個。最後,Foundation版本僅提供OEM廠商安裝使用,支援一般功能,限制15個使用者帳戶,售價未公開。

Datacenter版本與Standard版本在所提供的服務功能上是相同的,兩者唯一的差別在於虛擬機器的使用數量限制,使用者可根據VM需求選擇所要購買的版本。
/***
|''Name:''|abego.IncludePlugin|
|''Version:''|1.0.0 (2007-02-08)|
|''Type:''|plugin|
|''Source:''|http://tiddlywiki.abego-software.de/#IncludePlugin|
|''Author:''|Udo Borkowski (ub [at] abego-software [dot] de)|
|''Documentation:''|[[IncludePlugin Documentation|http://tiddlywiki.abego-software.de/#%5B%5BIncludePlugin%20Documentation%5D%5D]]|
|''Community:''|([[del.icio.us|http://del.icio.us/post?url=http://tiddlywiki.abego-software.de/index.html%23IncludePlugin]]) ([[Support|http://groups.google.com/group/TiddlyWiki]])|
|''Copyright:''|&copy; 2007 [[abego Software|http://www.abego-software.de]]|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''~CoreVersion:''|2.1.3|
|''Browser:''|Firefox 1.5.0.9 or better; Internet Explorer 6.0|
***/
//{{{

// Ensure the global abego namespace is set up.
if (!window.abego) window.abego = {};

var invokeLater = function(func, delay, priority) {
	return abego.invokeLater ? abego.invokeLater(func, delay, priority) : setTimeout(func,delay);
};

// Asynchronously load the given (local or remote) file.
// 
// @param url 		either an URL or a local file path to a file
//					Examples:
//						* http://www.abego-software.de/index.html
//						* file:///C:/abegoWebSite-Copy/index.html
//						* C:\abegoWebSite-Copy\index.html    (for Windows machines)
//							(Notice: backslashes in JavaScript string constants must be escaped, 
//							 i.e. the last example must be written as: "C:\\abegoWebSite-Copy\\index.html"
//							 when "hardcoded" in JavaScript source code)
// 
// @param callback 
//					function(content,url,params,errorMessage) 
//					called at the end of the operation. 
//					On success content holds the content of the loaded file. 
//					On error content is undefined and errorMessage holds an error message. 
//					params is the params passed into abego.loadFile.
//
// @param params 	passed through to the callback function
// 
abego.loadFile = function(url,callback,params) {

	var onLoad = function(status,params,responseText,url,xhr) {
		return status 
				? callback(responseText, url, params)
				: callback(undefined, url, params, "Error loading %0".format([url]));
	};
	
	// Make sure the URL is a real URL, with protocol prefix etc.
	if (url.search(/^((http(s)?)|(file)):/) != 0) {
		
		// no protocol specified. 
		if (url.search(/^((.\:\\)|(\\\\)|(\/))/) == 0) {
			// "url" is an "absolute" path to a local file. Prefix it with file://
			url = "file://"+url;
			
		} else {
			// "url" is a "relative" URL. Make it absolute
			
			// prefix the url with the directory containing the current document
			// (This also includes the protocol prefix)
			var documentPath = document.location.toString();
			var i = documentPath.lastIndexOf("/");
			url = documentPath.substr(0,i+1)+url;
		}
		// replace every \ by a /, to cover Windows style pathes
		url = url.replace(/\\/mg,"/");
	}
	
	loadRemoteFile(url,onLoad,params);

};

// Asynchronously load the given (local or remote) TiddlyWiki store.
// 
// @param url 		either an URL or a local file path to a TiddlyWiki file (absolute or relative)
//					Examples:
//						* http://www.abego-software.de/index.html
//						* file:///C:/abegoWebSite-Copy/index.html
//						* include/beta.html
//						* C:\abegoWebSite-Copy\index.html    (for Windows machines)
//							(Notice: backslashes in JavaScript string constants must be escaped, 
//							 i.e. the last example must be written as: "C:\\abegoWebSite-Copy\\index.html"
//							 when "hardcoded" in JavaScript source code)
// 
// @param callbackWithStore 
//					function(theStore,url,params,errorMessage) 
//					called at the end of the operation. 
//					On success theStore holds the loaded store (a TiddlyWiki object). 
//					On error theStore is undefined and errorMessage holds an error message. 
//					params is the params passed into abego.loadTiddlyWikiStore
//
// @param params 	passed through to the callbackWithStore
//
// @progress		[optional] function(message, sender, state, url, params) called in various situations during the operation,
//								typically used to show "the progress" of the operation.
//								sender: the constant "abego.loadTiddlyWikiStore"
//								state: one of these: "Started", "Processing", "Done", "Failed"
//									"Processing" means the data has been received and in now processed.
// 
abego.loadTiddlyWikiStore = function(url,callbackWithStore,params,progress) {
	
	var sendProgress = function(message, state) {
		if (progress)
			progress(message,"abego.loadTiddlyWikiStore",state,url,params);
	};
	
	// Load contents of a TiddlyWiki from a string
	//# Returns null on success, an error message otherwise.
	//# based on code from TiddlyWiki 2.2 alpha
	var importTiddlyWiki = function(store,text)
	{
		// Crack out the content - will be refactored to share code with saveChanges()
		var posOpeningDiv = text.indexOf(startSaveArea);
		var limitClosingDiv = text.indexOf("<!--POST-BODY-END--"+">");
		var posClosingDiv = text.lastIndexOf(endSaveArea,limitClosingDiv == -1 ? text.length : limitClosingDiv);
		if((posOpeningDiv == -1) || (posClosingDiv == -1))
			return config.messages.invalidFileError.format([url]);
		var content = "<html><body>" + text.substring(posOpeningDiv,posClosingDiv + endSaveArea.length) + "</body></html>";
		// Create the iframe
		var iframe = document.createElement("iframe");
		iframe.style.display = "none";
		document.body.appendChild(iframe);
		var doc = iframe.document;
		if(iframe.contentDocument)
			doc = iframe.contentDocument; // For NS6
		else if(iframe.contentWindow)
			doc = iframe.contentWindow.document; // For IE5.5 and IE6
		// Put the content in the iframe
		doc.open();
		doc.writeln(content);
		doc.close();
		// Load the content into a TiddlyWiki() object
		var storeArea = doc.getElementById("storeArea");
		store.loadFromDiv(storeArea,"store");
		// Get rid of the iframe
		iframe.parentNode.removeChild(iframe);
		return null;
	};
	
	var sendError = function(message) {
		sendProgress("Error when loading %0".format([url]),"Failed");
		callbackWithStore(undefined, url,params, message);
		return message;
	};
	
	var sendStore = function(store) {
		sendProgress("Loaded %0".format([url]),"Done");
		callbackWithStore(store, url, params);
		return null;
	};
	
	
	var callback = function(content,theURL,params,errorMessage) {
		if (content === undefined) {
			sendError(errorMessage);
			return;
		}
		
		sendProgress("Processing %0".format([url]),"Processing");
		var orig_invalidFileError = config.messages.invalidFileError;
		config.messages.invalidFileError = "The file '%0' does not appear to be a valid TiddlyWiki file";
		try {
			// Load the content into a TiddlyWiki() object
			var importStore = new TiddlyWiki();
			var errorText = importTiddlyWiki(importStore,content);
			if (errorText)
				sendError(errorText);
			else
				sendStore(importStore);

		} catch (ex) {
			sendError(exceptionText(ex));
		} finally {
			config.messages.invalidFileError = orig_invalidFileError;
		}
	};
	
	sendProgress("Start loading %0".format([url]),"Started");
	abego.loadFile(url,callback,params);
};


//==============================================================================
// Include Plugin 

(function(){

// only install once
if (abego.TiddlyWikiIncluder) return;


// --------------------------------------------------
// Constants

var WAITING = "waiting";
var LOADING = "loading";

var ANI_DURATION_HIDE_STATE = 1000;

var REFRESH_PRIORITY = -200;
var ANIMATION_PRIORITY = -100;
var UPDATE_STATE_PRIORITY = -300;

// --------------------------------------------------
// Variables

var useInclude;
var includes = []; // [] of Strings. the urls of the stores to include, in the sequence of the calls.
var includedStores = {}; // url(String) -> TiddlyWiki or String; when not (yet) loaded a status or error string.
var pendingOnLoadURLs = []; // [] of String. a list of urls that should be passed with the next "notifyListeners".
var refreshTiddlyWikiTimerID; // for delayed refresh
var listeners = [];
var progress;

// --------------------------------------------------
// Helper functions

var isIncludeEnabled = function() {
	if (useInclude === undefined)
		useInclude = config.options.chkUseInclude === undefined || config.options.chkUseInclude;
	return useInclude;
};

var getMissingIncludeMsg = function(url) {
	return "No include specified for %0".format([url])
};

// Called after one or more included TiddlyWikis are loaded
//
var notifyListeners = function() {
	var urls = pendingOnLoadURLs;
	pendingOnLoadURLs = [];
	if (urls.length) {
		for (var i= 0; i < listeners.length; i++)
			listeners[i](urls);
	}
};

var idleCount; // Reset to 0 when the system is "not idle", incremented inside refreshTiddlyWiki

var refreshTiddlyWiki = function() {
	// To avoid to much refreshing/flickering don't refresh immediately 
	// but wait until the system was idle for a certain time.
	
	if (refreshTiddlyWikiTimerID !== undefined) clearInterval(refreshTiddlyWikiTimerID);
	
	idleCount = 0;
	
	var sendDone = function() {
		abego.TiddlyWikiIncluder.sendProgress("","","Done");
	};
	
	refreshTiddlyWikiTimerID = setInterval(function() {
		idleCount++;
		if (idleCount <= 10)
			return;
			
		clearInterval(refreshTiddlyWikiTimerID);
		refreshTiddlyWikiTimerID = undefined;
			
		abego.TiddlyWikiIncluder.sendProgress("Refreshing...","","");
		refreshDisplay();
		invokeLater(sendDone,0,REFRESH_PRIORITY);
	},0);
};

// Calls callback for every loaded store and returns the first non-false/null.. value returned by callback.
//
// @param callback  function(store, url)
//
var forEachLoadedStore = function(callback) {
	var result;
	for (var i = 0; i < includes.length; i++) {
		var theStore = abego.TiddlyWikiIncluder.getStore(includes[i]);
		if (theStore && (result = callback(theStore, includes[i])))
			return result;
	}
};

var attachToStore = function() {
	if (!window.store)
		return invokeLater(attachToStore,100);
		
	var orig_fetchTiddler = store.fetchTiddler;
	
	store.fetchTiddler = function(title) {
		var t = orig_fetchTiddler.apply(this,arguments);
		if (t) return t;
		
		// When there is a shadowtiddler with that name done look for
		// any included tiddler since these would hide the shadow
		if (config.shadowTiddlers[title] !== undefined) return undefined;
		
		// Don't look for the "New Tiddler" tiddler in the included TiddlyWikis,
		// since returning such a tiddler (that is readonly) will make it impossible
		// in the Main TiddlyWiki to create new tiddlers.
		if (title == config.macros.newTiddler.title) return undefined;

		return forEachLoadedStore(
				function(theStore, url) {
					var t = theStore.fetchTiddler(title);
					if (t) 
						t.includeURL = url;
					return t;
				});
	};

	// We also refresh TiddlyWiki to reflect the new included Tiddlers (if we have any).
	if (includes.length)
		refreshTiddlyWiki();
};

var includeFromIncludeList = function() {
	if (!window.store)
		return invokeLater(includeFromIncludeList,100);
		
	var includeListText = store.getTiddlerText("IncludeList");
	if (includeListText) 
		wikify(includeListText,document.createElement("div"));
};

var getFunctionUsingForReallyEachTiddler = function(func) {
	var wrapper = function() {
		var orig_forEachTiddler = store.forEachTiddler;

		var forEachTiddlerWithIncludes = function(callback) {
			var done = {};
			var includeURL;

			var callbackWrapper = function(title, tiddler) {
				// ensure every title is only processed once
				if (done[title]) 
					return;
				done[title] = 1;
				
				// for "included tiddlers" set the includeURL;
				if (includeURL)
					tiddler.includeURL = includeURL;
				
				callback.apply(this,arguments);
			};
			
			// forEachTiddler over the original tiddlers
			orig_forEachTiddler.call(store, callbackWrapper);
			
			// add all shadowTiddler titles to done 
			// (to avoid an included store hides a shadow tiddler)
			for (var n in config.shadowTiddlers)
				done[n] = 1;

			// add all the "New Tiddler" tiddlerto done 
			// (to avoid an included store (with "New Tiddler") makes it impossible to create new tiddlers)
			done[config.macros.newTiddler.title] = 1;

			// forEachTiddler over every included store
			forEachLoadedStore(
					function(theStore, url) {
						includeURL = url;
						theStore.forEachTiddler(callbackWrapper);
					});
		};
		
		store.forEachTiddler = forEachTiddlerWithIncludes;
		try {
			return func.apply(this,arguments);
		} finally {
			store.forEachTiddler = orig_forEachTiddler;
		}
	};
	
	return wrapper;
};

var useForReallyEachTiddler = function(object,property) {
	return object[property] = getFunctionUsingForReallyEachTiddler(object[property]);
};


//================================================================================
// abego.TiddlyWikiIncluder

abego.TiddlyWikiIncluder = {};

abego.TiddlyWikiIncluder.setProgressFunction = function(func) {
	progress = func;
};

abego.TiddlyWikiIncluder.getProgressFunction = function(func) {
	return progress;
};

abego.TiddlyWikiIncluder.sendProgress = function(message, sender, state) {
	if (progress)
		progress.apply(this,arguments);
};


// Called when an included TiddlyWiki could not be loaded.
//
// By default an error message is displayed.
//
abego.TiddlyWikiIncluder.onError = function(url, errorMessage) {
	displayMessage("Error when including '%0':\n%1".format([url, errorMessage]));
};


// Returns true when there are "pending" includes, i.e. TiddlyWiki that are not yet loaded.
//
// A TiddlyWiki that failed loading is not pending.
//
abego.TiddlyWikiIncluder.hasPendingIncludes = function() {
	for (var i = 0; i < includes.length; i++) {
		var state = abego.TiddlyWikiIncluder.getState(includes[i]);
		if (state == WAITING || state == LOADING)
			return true;
	}
	return false;
};


// @return [] of Strings, the URLs of the includes
//
abego.TiddlyWikiIncluder.getIncludes = function() {
	return includes.slice();
};


// @return [may be null] a state/error text of the store with the given URL, or null when the store is already loaded
//
abego.TiddlyWikiIncluder.getState = function(url) {
	var s = includedStores[url];
	if (!s)
		return getMissingIncludeMsg(url);
	return typeof s == "string" ? s : null;
};


// @return [may be null] the (TiddlyWiki) store  with the given URL, null if not (yet) loaded.
//
abego.TiddlyWikiIncluder.getStore = function(url) {
	var s = includedStores[url];
	if (!s)
		return getMissingIncludeMsg(url);
	return s instanceof TiddlyWiki ? s : null;
};


// Includes the (local or remote) TiddlyWiki store with the given url.
// 
// stores with urls already already included are ignored.
//
// @param url	see url@abego.loadTiddlyWikiStore
// @param delayMilliSeconds [optional] if defined loading starts delayMilliSeconds later, otherwise "immediately"
//
abego.TiddlyWikiIncluder.include = function(url, delayMilliSeconds) {
	if (!isIncludeEnabled() || includedStores[url])
		return;
	var self = this;
	
	includes.push(url);
	includedStores[url] = WAITING;

	var loadStoreCallback = function(theStore,urlInCallback,params,errorMessage) {
		if (theStore === undefined) {
			includedStores[url] = errorMessage;
			self.onError(url, errorMessage);
			return;
		}
		includedStores[url] = theStore;
		pendingOnLoadURLs.push(url);
		invokeLater(notifyListeners);
	};
	
	var loadStore = function() {
		includedStores[url] = LOADING;
		abego.loadTiddlyWikiStore(url,loadStoreCallback,null,progress);
	};
	
	if (delayMilliSeconds)
		invokeLater(loadStore, delayMilliSeconds);
	else
		loadStore();
};


// iterates over all tiddlers of "the store" and all tiddlers of included (and loaded) stores
//
abego.TiddlyWikiIncluder.forReallyEachTiddler = function(callback) {
	var caller = function() {
		store.forEachTiddler(callback);
	};
	
	getFunctionUsingForReallyEachTiddler(caller).call(store);
};


// function abego.TiddlyWikiIncluder.getFunctionUsingForReallyEachTiddler(func)
//
// Returns a function that behaves as func, but every call to store.forEachTiddler will actually 
// be a call to forReallyEachTiddler, i.e. iterate over the tiddlers the main store and of the 
// included TiddlyWikis
//
// @return the patched function
//
abego.TiddlyWikiIncluder.getFunctionUsingForReallyEachTiddler = getFunctionUsingForReallyEachTiddler;


// function abego.TiddlyWikiIncluder.useForReallyEachTiddler(object,property)
//
// Patches the function hold in the given property of the object in such a way that every call
// to store.forEachTiddler will actually be a call to forReallyEachTiddler, i.e. iterate over the
// tiddlers the main staire and of the included TiddlyWikis
//
// @param object
// @param property the name of the property of the object containing the function to be patched.
// @return the patched function
//
abego.TiddlyWikiIncluder.useForReallyEachTiddler = useForReallyEachTiddler;


// Add a listener function to the TiddlyWikiIncluder.
//
// @param listener function(urls)
//							url: [] of Strings, containing the urls of the TiddlyWiki just included
//									(see url@abego.TiddlyWikiIncluder.include)
//						called whenever one or more TiddlyWiki store are successfully included.
//
abego.TiddlyWikiIncluder.addListener = function(listener) {
	listeners.push(listener);
};

// -------------------------------------------------------------------------------
// TiddlyWikiIncluder initialization code

abego.TiddlyWikiIncluder.addListener(refreshTiddlyWiki);

//----------------------------------------------------------------------------
// Options Support

if (config.options.chkUseInclude === undefined) config.options.chkUseInclude = true;

config.shadowTiddlers.AdvancedOptions += "\n<<option chkUseInclude>> Include ~TiddlyWikis (IncludeList | IncludeState | [[help|http://tiddlywiki.abego-software.de/#%5B%5BIncludePlugin%20Documentation%5D%5D]])\n^^(Reload this ~TiddlyWiki to make changes become effective)^^";
config.shadowTiddlers.IncludeState = "<<includeState>>";

//================================================================================
// Default Progress Handling for abego.TiddlyWikiIncluder

var showAnimated = function(e, showing, duration) {
	if (!anim || !abego.ShowAnimation) {
		e.style.display = showing ? "block" : "none";
		return;
	}
	
	anim.startAnimating(new abego.ShowAnimation(e,showing,duration));
};

abego.TiddlyWikiIncluder.getDefaultProgressFunction = function() {

	setStylesheet(
		".includeProgressState{\n"+
		"background-color:#FFCC00;\n"+
		"position:absolute;\n"+
		"right:0.2em;\n"+
		"top:0.2em;\n"+
		"width:7em;\n"+
		"padding-left:0.2em;\n"+
		"padding-right:0.2em\n"+
		"}\n",
		"abegoInclude");

	var createStateElem = function() {
		var e = document.createElement("div");
		e.className = "includeProgressState";
		e.style.display = "none";
		document.body.appendChild(e);
		return e;
	};
	
	var stateElem = createStateElem();


	var showState = function(message) {
		removeChildren(stateElem);
		createTiddlyText(stateElem,message);
		showAnimated(stateElem,true,0);
	};

	var hideState = function() {
		// hide the state the next idle time 
		invokeLater(function() {
			showAnimated(stateElem,false,ANI_DURATION_HIDE_STATE);
		},100,ANIMATION_PRIORITY);
	};
	
	var myProgressFunction = function(message, sender, state, url, params) {
		
		if (state == "Done" || state == "Failed") {
			hideState();
			return;
		}
		
		if (sender == "abego.loadTiddlyWikiStore") {
			idleCount = 0;
			if (state == "Processing")
				showState("Including...");
		} else {
			showState(message);
		}
	};
	return myProgressFunction;
};

abego.TiddlyWikiIncluder.setProgressFunction(abego.TiddlyWikiIncluder.getDefaultProgressFunction());


//================================================================================
// The "include" macro
//
// Syntax: <<include {url}* [delay: {milliSeconds}] [hide: true] >>
//

config.macros.include = {};
config.macros.include.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
    params = paramString.parseParams("url",null,true,false,true); // allowEval, cascadeDefaults, names allowed
	var delay = parseInt(getParam(params,"delay","0"));
	var urls = params[0]["url"];
	var hide = getFlag(params, "hide", false);
	if (!hide)
		createTiddlyText(createTiddlyElement(place,"code"),wikifier.source.substring(wikifier.matchStart, wikifier.nextMatch));
	for (var i = 0; urls && i < urls.length; i++)
		abego.TiddlyWikiIncluder.include(urls[i],delay);
};


//================================================================================
// The "includeState" macro
//
// Syntax: <<includeState>>

config.macros.includeState = {};
config.macros.includeState.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
	var getFullState = function () {
		var s = "";
		var includes = abego.TiddlyWikiIncluder.getIncludes();
		if (!includes.length)
			return "{{noIncludes{\nNo includes or 'include' is disabled (see AdvancedOptions)\n}}}\n";
			
		s += "|!Address|!State|\n";
		for (var i = 0; i < includes.length; i++) {
			var inc = includes[i];
			s += "|{{{"+inc+"}}}|";
			var t = abego.TiddlyWikiIncluder.getState(inc);
			s += t ? "{{{"+t+"}}}" : "included";
			s += "|\n"
		}
		s += "|includeState|k\n";
		return s;
	};
	
	var updateState = function(){
		removeChildren(div);
		wikify(getFullState(),div);
		if (abego.TiddlyWikiIncluder.hasPendingIncludes())
			invokeLater(updateState,500,UPDATE_STATE_PRIORITY);
	};

	var div = createTiddlyElement(place,"div");
	
	invokeLater(updateState,0,UPDATE_STATE_PRIORITY);
};

//================================================================================
// Tiddler extension/modification

var orig_Tiddler_isReadOnly = Tiddler.prototype.isReadOnly;

// Includes tiddlers are readonly.
Tiddler.prototype.isReadOnly = function() {
	return orig_Tiddler_isReadOnly.apply(this,arguments) || this.isIncluded();
}

Tiddler.prototype.isIncluded = function() {
	return this.includeURL != undefined;
};

Tiddler.prototype.getIncludeURL = function() {
	return this.includeURL;
};


//================================================================================
// TiddlyWiki modifications

// In some TiddlyWiki functions the "forEachTiddler" should work on all tiddlers, also those from 
// included store. (E.g. TiddlyWiki.prototype.getTags)
//
// But not for all (e.g. TiddlyWiki.prototype.getTiddlers is used for saving, but only the "own" tiddlers should be saved)
//
// Therefore explicitly list the functions that should be "wrapped" to use the "forReallyEachTiddler".
//
var tiddlyWikiFunctionsUsingForReallyEachTiddler = {
	getMissingLinks: 1, getOrphans: 1,getTags:1, reverseLookup: 1, updateTiddlers: 1};
	
for (var n in tiddlyWikiFunctionsUsingForReallyEachTiddler)
	useForReallyEachTiddler(TiddlyWiki.prototype,n);


//================================================================================
// Make IntelliTagger "Include-aware"

var patchIntelliTagger = function() {
	if (abego.IntelliTagger)
		useForReallyEachTiddler(abego.IntelliTagger,"assistTagging");
};

//================================================================================
// Perform plugin startup tasks

attachToStore();
invokeLater(includeFromIncludeList,100);
invokeLater(patchIntelliTagger,100);

})();

//}}}
/***
|''Name:''|easyEditPlugin|
|''Description:''|Lite and extensible Wysiwyg editor for TiddlyWiki.|
|''Version:''|1.3.3|
|''Date:''|Dec 21,2007|
|''Source:''|http://visualtw.ouvaton.org/VisualTW.html|
|''Author:''|Pascal Collin|
|''License:''|[[BSD open source license|License]]|
|''~CoreVersion:''|2.1.0|
|''Browser:''|Firefox 2.0; InternetExplorer 6.0|
!Installation
#import the plugin,
#save and reload,
#use the <<toolbar easyEdit>> button in the tiddler's toolbar (in default ViewTemplate) or add {{{easyEdit}}} command in your own toolbar.
! Useful Addons
*[[HTMLFormattingPlugin|http://www.tiddlytools.com/#HTMLFormattingPlugin]] to embed wiki syntax in html tiddlers.<<br>>//__Tips__ : When this plugin is installed, you can use anchor syntax to link tiddlers in wysiwyg mode (example : #example). Anchors are converted back and from wiki syntax when editing.//
*[[TaggedTemplateTweak|http://www.TiddlyTools.com/#TaggedTemplateTweak]] to use alternative ViewTemplate/EditTemplate for tiddler's tagged with specific tag values.
!Configuration
|Buttons in the toolbar (empty = all).<<br>>//Example : bold,underline,separator,forecolor//<<br>>The buttons will appear in this order.| <<option txtEasyEditorButtons>>|
|EasyEditor default height | <<option txtEasyEditorHeight>>|
|Stylesheet applied to the edited richtext |[[EasyEditDocStyleSheet]]|
|Template called by the {{{write}}} button |[[EasyEditTemplate]]|
!How to extend EasyEditor
*To add your own buttons, add some code like the following in a systemConfig tagged tiddler (//use the prompt attribute only if there is a parameter//) :
**{{{EditorToolbar.buttons.heading = {label:"H", toolTip : "Set heading level", prompt: "Enter heading level"};}}} 
**{{{EditorToolbar.buttonsList +=",heading";}}}
*To get the list of all possible commands, see the documentation of the [[Gecko built-in rich text editor|http://developer.mozilla.org/en/docs/Midas]] or the [[IE command identifiers|http://msdn2.microsoft.com/en-us/library/ms533049.aspx]].
*To go further in customization, see [[Link button|EasyEditPlugin-LinkButton]] as an example.
!Code
***/

//{{{

var geckoEditor={};
var IEeditor={};

config.options.txtEasyEditorHeight = config.options.txtEasyEditorHeight ? config.options.txtEasyEditorHeight : "500px";
config.options.txtEasyEditorButtons = config.options.txtEasyEditorButtons ? config.options.txtEasyEditorButtons : "";

// TW2.1.x compatibility
config.browser.isGecko = config.browser.isGecko ? config.browser.isGecko : (config.userAgent.indexOf("gecko") != -1); 
config.macros.annotations = config.macros.annotations ? config.macros.annotations : {handler : function() {}}


// EASYEDITOR MACRO

config.macros.easyEdit = {
	handler : function(place,macroName,params,wikifier,paramString,tiddler) {
		var field = params[0];
		var height = params[1] ? params[1] : config.options.txtEasyEditorHeight;
		var editor = field ? new easyEditor(tiddler,field,place,height) : null;
	},
	gather: function(element){
		var iframes = element.getElementsByTagName("iframe");
		if (iframes.length!=1) return null
		var text = "<html>"+iframes[0].contentWindow.document.body.innerHTML+"</html>";
		text = config.browser.isGecko ? geckoEditor.postProcessor(text) : (config.browser.isIE ? IEeditor.postProcessor(text) : text);
		return text;
	}
}

// EASYEDITOR CLASS

function easyEditor(tiddler,field,place,height) {
	this.tiddler = tiddler;
	this.field = field;
	this.browser = config.browser.isGecko ? geckoEditor : (config.browser.isIE ? IEeditor : null);
	this.wrapper = createTiddlyElement(place,"div",null,"easyEditor");
	this.wrapper.setAttribute("easyEdit",this.field);
	this.iframe = createTiddlyElement(null,"iframe");
	this.browser.setupFrame(this.iframe,height,contextualCallback(this,this.onload));
	this.wrapper.appendChild(this.iframe);
}

easyEditor.prototype.onload = function(){
	this.editor = this.iframe.contentWindow;
	this.doc = this.editor.document;
	if (!this.browser.isDocReady(this.doc)) return null;
	
	if (!this.tiddler.isReadOnly() && this.doc.designMode.toLowerCase()!="on") {
		this.doc.designMode = "on";
		if (this.browser.reloadOnDesignMode) return false;	// IE fire readystatechange after designMode change
	}
	
	var internalCSS = store.getTiddlerText("EasyEditDocStyleSheet");
	setStylesheet(internalCSS,"EasyEditDocStyleSheet",this.doc);
	this.browser.initContent(this.doc,store.getValue(this.tiddler,this.field));

	var barElement=createTiddlyElement(null,"div",null,"easyEditorToolBar");
	this.wrapper.insertBefore(barElement,this.wrapper.firstChild);
	this.toolbar = new EditorToolbar(this.doc,barElement,this.editor);

	this.browser.plugEvents(this.doc,contextualCallback(this,this.scheduleButtonsRefresh));
	this.editor.focus();
}

easyEditor.SimplePreProcessoror = function(text) {
	var re = /^<html>(.*)<\/html>$/m;
	var htmlValue = re.exec(text);
	var value = (htmlValue && (htmlValue.length>0)) ? htmlValue[1] : text;
	return value;
}

easyEditor.prototype.scheduleButtonsRefresh=function() { //doesn't refresh buttons state when rough typing
	if (this.nextUpdate) window.clearTimeout(this.nextUpdate);
	this.nextUpdate = window.setTimeout(contextualCallback(this.toolbar,EditorToolbar.onUpdateButton),easyEditor.buttonDelay);
}

easyEditor.buttonDelay = 200;

// TOOLBAR CLASS

function EditorToolbar(target,parent,window){
	this.target = target;
	this.window=window;
	this.elements={};
	var row = createTiddlyElement(createTiddlyElement(createTiddlyElement(parent,"table"),"tbody"),"tr");
	var buttons = (config.options.txtEasyEditorButtons ? config.options.txtEasyEditorButtons : EditorToolbar.buttonsList).split(",");
	for(var cpt = 0; cpt < buttons.length; cpt++){
		var b = buttons[cpt];
		var button = EditorToolbar.buttons[b];
		if (button) {
			if (button.separator)
				createTiddlyElement(row,"td",null,"separator").innerHTML+="&nbsp;";
			else {
				var cell=createTiddlyElement(row,"td",null,b+"Button");
				if (button.onCreate) button.onCreate.call(this, cell, b);
				else EditorToolbar.createButton.call(this, cell, b);
			}
		}
	}
}

EditorToolbar.createButton = function(place,name){
	this.elements[name] = createTiddlyButton(place,EditorToolbar.buttons[name].label,EditorToolbar.buttons[name].toolTip,contextualCallback(this,EditorToolbar.onCommand(name)),"button");
}

EditorToolbar.onCommand = function(name){
	var button = EditorToolbar.buttons[name];
	return function(){
		var parameter = false;
		if (button.prompt) {
			var parameter = this.target.queryCommandValue(name);
			parameter = prompt(button.prompt,parameter);
		}
		if (parameter != null) {
			this.target.execCommand(name, false, parameter);
			EditorToolbar.onUpdateButton.call(this);
		}
		return false;
	}
}

EditorToolbar.getCommandState = function(target,name){
	try {return target.queryCommandState(name)}
	catch(e){return false}
}

EditorToolbar.onRefreshButton = function (name){
	if (EditorToolbar.getCommandState(this.target,name)) addClass(this.elements[name].parentNode,"buttonON");
	else removeClass(this.elements[name].parentNode,"buttonON");
	this.window.focus();
}

EditorToolbar.onUpdateButton = function(){
	for (b in this.elements) 
		if (EditorToolbar.buttons[b].onRefresh) EditorToolbar.buttons[b].onRefresh.call(this,b);
		else EditorToolbar.onRefreshButton.call(this,b);
}

EditorToolbar.buttons = {
	separator : {separator : true},
	bold : {label:"B", toolTip : "Bold"},
	italic : {label:"I", toolTip : "Italic"},
	underline : {label:"U", toolTip : "Underline"},
	strikethrough : {label:"S", toolTip : "Strikethrough"},
	insertunorderedlist : {label:"\u25CF", toolTip : "Unordered list"},
	insertorderedlist : {label:"1.", toolTip : "Ordered list"},
	justifyleft : {label:"[\u2261", toolTip : "Align left"},
	justifyright : {label:"\u2261]", toolTip : "Align right"},
	justifycenter : {label:"\u2261", toolTip : "Align center"},
	justifyfull : {label:"[\u2261]", toolTip : "Justify"},
	removeformat : {label:"\u00F8", toolTip : "Remove format"},
	fontsize : {label:"\u00B1", toolTip : "Set font size", prompt: "Enter font size"},
	forecolor : {label:"C", toolTip : "Set font color", prompt: "Enter font color"},
	fontname : {label:"F", toolTip : "Set font name", prompt: "Enter font name"},
	heading : {label:"H", toolTip : "Set heading level", prompt: "Enter heading level (example : h1, h2, ...)"},
	indent : {label:"\u2192[", toolTip : "Indent paragraph"},
	outdent : {label:"[\u2190", toolTip : "Outdent paragraph"},
	inserthorizontalrule : {label:"\u2014", toolTip : "Insert an horizontal rule"},
	insertimage : {label:"\u263C", toolTip : "Insert image", prompt: "Enter image url"}
}

EditorToolbar.buttonsList = "bold,italic,underline,strikethrough,separator,increasefontsize,decreasefontsize,fontsize,forecolor,fontname,separator,removeformat,separator,insertparagraph,insertunorderedlist,insertorderedlist,separator,justifyleft,justifyright,justifycenter,justifyfull,indent,outdent,separator,heading,separator,inserthorizontalrule,insertimage";

if (config.browser.isGecko) {
	EditorToolbar.buttons.increasefontsize = {onCreate : EditorToolbar.createButton, label:"A", toolTip : "Increase font size"};
	EditorToolbar.buttons.decreasefontsize = {onCreate : EditorToolbar.createButton, label:"A", toolTip : "Decrease font size"};
	EditorToolbar.buttons.insertparagraph = {label:"P", toolTip : "Format as paragraph"};
}

// GECKO (FIREFOX, ...) BROWSER SPECIFIC METHODS

geckoEditor.setupFrame = function(iframe,height,callback) {
	iframe.setAttribute("style","width: 100%; height:" + height);
	iframe.addEventListener("load",callback,true);
}

geckoEditor.plugEvents = function(doc,onchange){
	doc.addEventListener("keyup", onchange, true);
	doc.addEventListener("keydown", onchange, true);
	doc.addEventListener("click", onchange, true);
}

geckoEditor.postProcessor = function(text){return text};

geckoEditor.preProcessor = function(text){return easyEditor.SimplePreProcessoror(text)}

geckoEditor.isDocReady = function() {return true;}

geckoEditor.reloadOnDesignMode=false;

geckoEditor.initContent = function(doc,content){
	if (content) doc.execCommand("insertHTML",false,geckoEditor.preProcessor(content));
}

// INTERNET EXPLORER BROWSER SPECIFIC METHODS
	
IEeditor.setupFrame = function(iframe,height,callback) {
	iframe.width="99%";  //IE displays the iframe at the bottom if 100%. CSS layout problem ? I don't know. To be studied...
	iframe.height=height.toString();
	iframe.attachEvent("onreadystatechange",callback);
}

IEeditor.plugEvents = function(doc,onchange){
	doc.attachEvent("onkeyup", onchange);
	doc.attachEvent("onkeydown", onchange);
	doc.attachEvent("onclick", onchange);
}

IEeditor.isDocReady = function(doc){
	if (doc.readyState!="complete") return false;
	if (!doc.body) return false;
	return (doc && doc.getElementsByTagName && doc.getElementsByTagName("head") && doc.getElementsByTagName("head").length>0);
}

IEeditor.postProcessor = function(text){return text};

IEeditor.preProcessor = function(text){return easyEditor.SimplePreProcessoror(text)}

IEeditor.reloadOnDesignMode=true;

IEeditor.initContent = function(doc,content){
	if (content) doc.body.innerHTML=IEeditor.preProcessor(content);
}
	
function contextualCallback(obj,func){
    return function(){return func.call(obj)}
}
	
Story.prototype.previousGatherSaveEasyEdit = Story.prototype.previousGatherSaveEasyEdit ? Story.prototype.previousGatherSaveEasyEdit : Story.prototype.gatherSaveFields; // to avoid looping if this line is called several times
Story.prototype.gatherSaveFields = function(e,fields){
	if(e && e.getAttribute) {
		var f = e.getAttribute("easyEdit");
		if(f){
			var newVal = config.macros.easyEdit.gather(e);
			if (newVal) fields[f] = newVal;
		}
		this.previousGatherSaveEasyEdit(e, fields);
	}
}

config.commands.easyEdit={
	text: "編輯網頁",
	tooltip: "Edit this tiddler in wysiwyg mode",
	readOnlyText: "檢視",
	readOnlyTooltip: "View the source of this tiddler",
	handler : function(event,src,title) {
		clearMessage();
		var tiddlerElem = document.getElementById(story.idPrefix + title);
		var fields = tiddlerElem.getAttribute("tiddlyFields");
		story.displayTiddler(null,title,"EasyEditTemplate",false,null,fields);
		return false;
	}
}

config.shadowTiddlers.ViewTemplate = config.shadowTiddlers.ViewTemplate.replace(/\+editTiddler/,"+editTiddler easyEdit");

config.shadowTiddlers.EasyEditTemplate = config.shadowTiddlers.EditTemplate.replace(/macro='edit text'/,"macro='easyEdit text'");

config.shadowTiddlers.EasyEditToolBarStyleSheet = "/*{{{*/\n";
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar {font-size:0.8em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".editor iframe {border:1px solid #DDD}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar td{border:1px solid #888; padding:2px 1px 2px 1px; vertical-align:middle}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar td.separator{border:0}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .button{border:0;color:#444}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .buttonON{background-color:#EEE}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar {margin:0.25em 0}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .boldButton {font-weight:bold}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .italicButton .button {font-style:italic;padding-right:0.65em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .underlineButton .button {text-decoration:underline}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .strikeButton .button {text-decoration:line-through}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .unorderedListButton {margin-left:0.7em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .justifyleftButton .button {padding-left:0.1em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .justifyrightButton .button {padding-right:0.1em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .justifyfullButton .button, .easyEditorToolBar .indentButton .button, .easyEditorToolBar .outdentButton .button {padding-left:0.1em;padding-right:0.1em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .increasefontsizeButton .button {padding-left:0.15em;padding-right:0.15em; font-size:1.3em; line-height:0.75em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .decreasefontsizeButton .button {padding-left:0.4em;padding-right:0.4em; font-size:0.8em;}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .forecolorButton .button {color:red;}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .fontnameButton .button {font-family:serif}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet +="/*}}}*/";

store.addNotification("EasyEditToolBarStyleSheet", refreshStyles); 

config.shadowTiddlers.EasyEditDocStyleSheet = "/*{{{*/\n \n/*}}}*/";
if (config.annotations) config.annotations.EasyEditDocStyleSheet = "This stylesheet is applied when editing a text with the wysiwyg easyEditor";

//}}}
/***
!Link button add-on
***/
//{{{
EditorToolbar.createLinkButton = function(place,name) {
	this.elements[name] = createTiddlyButton(place,EditorToolbar.buttons[name].label,EditorToolbar.buttons[name].toolTip,contextualCallback(this,EditorToolbar.onInputLink()),"button");
}

EditorToolbar.onInputLink = function() {
	return function(){
		var browser = config.browser.isGecko ? geckoEditor : (config.browser.isIE ? IEeditor : null);
		var value = browser ? browser.getLink(this.target) : "";
		value = prompt(EditorToolbar.buttons["createlink"].prompt,value);
		if (value) browser.doLink(this.target,value);
		else if (value=="") this.target.execCommand("unlink", false, value);
		EditorToolbar.onUpdateButton.call(this);
		return false;
	}
}

EditorToolbar.buttonsList += ",separator,createlink";

EditorToolbar.buttons.createlink = {onCreate : EditorToolbar.createLinkButton, label:"L", toolTip : "Set link", prompt: "Enter link url"};


geckoEditor.getLink=function(doc){
	var range=doc.defaultView.getSelection().getRangeAt(0);
	var container = range.commonAncestorContainer;
	var node = (container.nodeType==3) ? container.parentNode : range.startContainer.childNodes[range.startOffset];
	if (node && node.tagName=="A") {
		var r=doc.createRange();
		r.selectNode(node);
		doc.defaultView.getSelection().addRange(r);
		return (node.getAttribute("tiddler") ? "#"+node.getAttribute("tiddler") : node.href);
	}
	else return (container.nodeType==3 ? "#"+container.textContent.substr(range.startOffset, range.endOffset-range.startOffset).replace(/ $/,"") : "");
}

geckoEditor.doLink=function(doc,link){ // store tiddler in a temporary attribute to avoid url encoding of tiddler's name
	var pin = "href"+Math.random().toString().substr(3);
	doc.execCommand("createlink", false, pin);
	var isTiddler=(link.charAt(0)=="#");
	var node = doc.defaultView.getSelection().getRangeAt(0).commonAncestorContainer;
	var links= (node.nodeType!=3) ? node.getElementsByTagName("a") : [node.parentNode];
	for (var cpt=0;cpt<links.length;cpt++) 
			if (links[cpt].href==pin){
				links[cpt].href=isTiddler ? "javascript:;" : link; 
				links[cpt].setAttribute("tiddler",isTiddler ? link.substr(1) : "");
			}
}

geckoEditor.beforeLinkPostProcessor = geckoEditor.beforelinkPostProcessor ? geckoEditor.beforelinkPostProcessor : geckoEditor.postProcessor;
geckoEditor.postProcessor = function(text){
	return geckoEditor.beforeLinkPostProcessor(text).replace(/<a tiddler="([^"]*)" href="javascript:;">(.*?)(?:<\/a>)/gi,"[[$2|$1]]").replace(/<a tiddler="" href="/gi,'<a href="');
}

geckoEditor.beforeLinkPreProcessor = geckoEditor.beforeLinkPreProcessor ? geckoEditor.beforeLinkPreProcessor : geckoEditor.preProcessor
geckoEditor.preProcessor = function(text){
	return geckoEditor.beforeLinkPreProcessor(text).replace(/\[\[([^|\]]*)\|([^\]]*)]]/g,'<a tiddler="$2" href="javascript:;">$1</a>');
}


IEeditor.getLink=function(doc){
	var node=doc.selection.createRange().parentElement();
	if (node.tagName=="A") return node.href;
	else return (doc.selection.type=="Text"? "#"+doc.selection.createRange().text.replace(/ $/,"") :"");
}

IEeditor.doLink=function(doc,link){
	doc.execCommand("createlink", false, link);
}

IEeditor.beforeLinkPreProcessor = IEeditor.beforeLinkPreProcessor ? IEeditor.beforeLinkPreProcessor : IEeditor.preProcessor
IEeditor.preProcessor = function(text){
	return IEeditor.beforeLinkPreProcessor(text).replace(/\[\[([^|\]]*)\|([^\]]*)]]/g,'<a ref="#$2">$1</a>');
}

IEeditor.beforeLinkPostProcessor = IEeditor.beforelinkPostProcessor ? IEeditor.beforelinkPostProcessor : IEeditor.postProcessor;
IEeditor.postProcessor = function(text){
	return IEeditor.beforeLinkPostProcessor(text).replace(/<a href="#([^>]*)">([^<]*)<\/a>/gi,"[[$2|$1]]");
}

IEeditor.beforeLinkInitContent = IEeditor.beforeLinkInitContent ? IEeditor.beforeLinkInitContent : IEeditor.initContent;
IEeditor.initContent = function(doc,content){
	IEeditor.beforeLinkInitContent(doc,content);
	var links=doc.body.getElementsByTagName("A");
	for (var cpt=0; cpt<links.length; cpt++) {
		links[cpt].href=links[cpt].ref; //to avoid IE conversion of relative URLs to absolute
		links[cpt].removeAttribute("ref");	
	}
}

config.shadowTiddlers.EasyEditToolBarStyleSheet += "\n/*{{{*/\n.easyEditorToolBar .createlinkButton .button {color:blue;text-decoration:underline;}\n/*}}}*/";

config.shadowTiddlers.EasyEditDocStyleSheet += "\n/*{{{*/\na {color:#0044BB;font-weight:bold}\n/*}}}*/";

//}}}
//{{{
//============================================================================
// getCreateDate Function
//============================================================================
//
// Returns the "create date" as generated by the AutoTaggerPlugin
// (http://www.TiddlyTools.com/#AutoTaggerPlugin).
// The create date must be stored in the default format "YYYY.0MM.0DD".
//
// @return [may be null] the create date (as a String) or null if no create 
// date is found.
//
version.extensions.getCreateDate = {major: 1, minor: 0, revision: 0, 
 date: new Date(2005,11,21), 
 provider: "http://tiddlywiki.abego-software.de"};
//
function getCreateDate(tiddler) {
 if (!tiddler || !tiddler.tags) {
 return null;
 }

 for(var i = 0; i < tiddler.tags.length; i++) {
 var matches = tiddler.tags[i].match(/^[0-9]{4}\.[0-9]{2}\.[0-9]{2}$/);
 if (matches && matches.length > 0) {
 return matches[0];
 }
 }
 return null;
}

//}}}
/***
|''Name:''|zh-HantTranslationPlugin|
|''Description:''|Translation of TiddlyWiki into Traditional Chinese|
|''Source:''|http://tiddlywiki-zh.googlecode.com/svn/trunk/|
|''Subversion:''|http://svn.tiddlywiki.org/Trunk/association/locales/core/zh-Hant/locale.zh-Hant.js|
|''Author:''|BramChen (bram.chen (at) gmail (dot) com)|
|''Version:''|2.2.6|
|''Date:''|Dec 01, 2007|
|''Comments:''|Please make comments at http://groups-beta.google.com/group/TiddlyWiki-zh/|
|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|''~CoreVersion:''|2.2.0|
***/

//{{{
// --
// -- Translateable strings
// --

// Strings in "double quotes" should be translated; strings in 'single quotes' should be left alone

config.locale = 'zh-Hant'; // W3C language tag

if (config.options.txtUserName == 'YourName' || !config.options.txtUserName) // do not translate this line, but do translate the next line
	merge(config.options,{txtUserName: "YourName"});

merge(config.tasks,{
	save: {text: "儲存", tooltip: "儲存變更至此 TiddlyWiki", action: saveChanges},
	sync: {text: "同步", tooltip: "將你的資料內容與外部伺服器與檔案同步", content: '<<sync>>'},
	importTask: {text: "導入", tooltip: "自其他檔案或伺服器導入文章或套件", content: '<<importTiddlers>>'},
	tweak: {text: "選項", tooltip: "改變此 TiddlyWiki 的顯示與行為的設定", content: '<<options>>'},
	plugins: {text: "套件管理", tooltip: "管理已安裝的套件", content: '<<plugins>>'}
});

merge(config.optionsDesc,{
	txtUserName: "編輯文章所使用之作者署名",
	chkRegExpSearch: "啟用正規式搜尋",
	chkCaseSensitiveSearch: "搜尋時,區分大小寫",
	chkAnimate: "使用動畫顯示",
	chkSaveBackups: "儲存變更前,保留備份檔案",
	chkAutoSave: "自動儲存變更",
	chkGenerateAnRssFeed: "儲存變更時,也儲存 RSS feed",
	chkSaveEmptyTemplate: "儲存變更時,也儲存空白範本",
	chkOpenInNewWindow: "於新視窗開啟連結",
	chkToggleLinks: "點擊已開啟文章將其關閉",
	chkHttpReadOnly: "非本機瀏覽文件時,隱藏編輯功能",
	chkForceMinorUpdate: "修改文章時,不變更作者名稱與日期時間",
	chkConfirmDelete: "刪除文章前須確認",
	chkInsertTabs: "使用 tab 鍵插入定位字元,而非跳至下一個欄位",
	txtBackupFolder: "存放備份檔案的資料夾",
	txtMaxEditRows: "編輯模式中顯示列數",
	txtFileSystemCharSet: "指定儲存文件所在之檔案系統之字集 (僅適用於 Firefox/Mozilla only)"});

// Messages
merge(config.messages,{
	customConfigError: "套件載入發生錯誤,詳細請參考 PluginManager",
	pluginError: "發生錯誤: %0",
	pluginDisabled: "未執行,因標籤設為 'systemConfigDisable'",
	pluginForced: "已執行,因標籤設為 'systemConfigForce'",
	pluginVersionError: "未執行,套件需較新版本的 TiddlyWiki",
	nothingSelected: "尚未作任何選擇,至少需選擇一項",
	savedSnapshotError: "此 TiddlyWiki 未正確存檔,詳見 http://www.tiddlywiki.com/#DownloadSoftware",
	subtitleUnknown: "(未知)",
	undefinedTiddlerToolTip: "'%0' 尚無內容",
	shadowedTiddlerToolTip: "'%0' 尚無內容, 但已定義隱藏的預設值",
	tiddlerLinkTooltip: "%0 - %1, %2",
	externalLinkTooltip: "外部連結至 %0",
	noTags: "未設定標籤的文章",
	notFileUrlError: "須先將此 TiddlyWiki 存至檔案,才可儲存變更",
	cantSaveError: "無法儲存變更。可能的原因有:\n- 你的瀏覽器不支援此儲存功能(Firefox, Internet Explorer, Safari and Opera 經適當設定後可儲存變更)\n- 也可能是你的 TiddlyWiki 檔名包含不合法的字元所致。\n- 或是 TiddlyWiki 文件被改名或搬移。",
	invalidFileError: " '%0' 非有效之 TiddlyWiki 文件",
	backupSaved: "已儲存備份",
	backupFailed: "無法儲存備份",
	rssSaved: "RSS feed 已儲存",
	rssFailed: "無法儲存 RSS feed ",
	emptySaved: "已儲存範本",
	emptyFailed: "無法儲存範本",
	mainSaved: "主要的TiddlyWiki已儲存",
	mainFailed: "無法儲存主要 TiddlyWiki,所作的改變未儲存",
	macroError: "巨集 <<\%0>> 執行錯誤",
	macroErrorDetails: "執行巨集 <<\%0>> 時,發生錯誤 :\n%1",
	missingMacro: "無此巨集",
	overwriteWarning: "'%0' 已存在,[確定]覆寫之",
	unsavedChangesWarning: "注意! 尚未儲存變更\n\n[確定]存檔,或[取消]放棄存檔?",
	confirmExit: "--------------------------------\n\nTiddlyWiki 以更改內容尚未儲存,繼續的話將遺失這些更動\n\n--------------------------------",
	saveInstructions: "SaveChanges",
	unsupportedTWFormat: "未支援此 TiddlyWiki 格式:'%0'",
	tiddlerSaveError: "儲存文章 '%0' 時,發生錯誤。",
	tiddlerLoadError: "載入文章 '%0' 時,發生錯誤。",
	wrongSaveFormat: "無法使用格式 '%0' 儲存,請使用標准格式存放",
	invalidFieldName: "無效的欄位名稱:%0",
	fieldCannotBeChanged: "無法變更欄位:'%0'",
	loadingMissingTiddler: "正從伺服器 '%1' 的:\n\n工作區 '%3' 中的 '%2' 擷取文章 '%0'"});

merge(config.messages.messageClose,{
	text: "關閉",
	tooltip: "關閉此訊息"});

config.messages.backstage = {
	open: {text: "控制台", tooltip: "開啟控制台執行編寫工作"},
	close: {text: "關閉", tooltip: "關閉控制台"},
	prompt: "控制台:",
	decal: {
		edit: {text: "編輯", tooltip: "編輯 '%0'"}
	}
};

config.messages.listView = {
	tiddlerTooltip: "檢視全文",
	previewUnavailable: "(無法預覽)"
};

config.messages.dates.months = ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"];
config.messages.dates.days = ["星期日", "星期一","星期二", "星期三", "星期四", "星期五", "星期六"];
// config.messages.dates.shortMonths = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
config.messages.dates.shortMonths = ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"];
// config.messages.dates.shortDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
config.messages.dates.shortDays = ["日", "一","二", "三", "四", "五", "六"];
// suffixes for dates, eg "1st","2nd","3rd"..."30th","31st"
config.messages.dates.daySuffixes = ["st","nd","rd","th","th","th","th","th","th","th",
		"th","th","th","th","th","th","th","th","th","th",
		"st","nd","rd","th","th","th","th","th","th","th",
		"st"];
config.messages.dates.am = "上午";
config.messages.dates.pm = "下午";

merge(config.messages.tiddlerPopup,{ 
	});

merge(config.views.wikified.tag,{
	labelNoTags: "未設標籤",
	labelTags: "標籤: ",
	openTag: "開啟標籤 '%0'",
	tooltip: "顯示標籤為 '%0' 的文章",
	openAllText: "開啟以下所有文章",
	openAllTooltip: "開啟以下所有文章",
	popupNone: "僅此文標籤為 '%0'"});

merge(config.views.wikified,{
	defaultText: "",
	defaultModifier: "(未完成)",
	shadowModifier: "(預設)",
	dateFormat: "YYYY年0MM月0DD日",
	createdPrompt: "建立於"});

merge(config.views.editor,{
	tagPrompt: "設定標籤之間以空白區隔,[[標籤含空白時請使用雙中括弧]],或點選現有之標籤加入",
	defaultText: ""});

merge(config.views.editor.tagChooser,{
	text: "標籤",
	tooltip: "點選現有之標籤加至本文章",
	popupNone: "未設定標籤",
	tagTooltip: "加入標籤 '%0'"});

merge(config.messages,{
	sizeTemplates:
		[
		{unit: 1024*1024*1024, template: "%0\u00a0GB"},
		{unit: 1024*1024, template: "%0\u00a0MB"},
		{unit: 1024, template: "%0\u00a0KB"},
		{unit: 1, template: "%0\u00a0B"}
		]});

merge(config.macros.search,{
	label: " 尋找",
	prompt: "搜尋本 Wiki",
	accessKey: "F",
	successMsg: " %0 篇符合條件: %1",
	failureMsg: " 無符合條件: %0"});

merge(config.macros.tagging,{
	label: "引用標籤:",
	labelNotTag: "無引用標籤",
	tooltip: "列出標籤為 '%0' 的文章"});

merge(config.macros.timeline,{
	dateFormat: "YYYY年0MM月0DD日"});

merge(config.macros.allTags,{
	tooltip: "顯示文章- 標籤為'%0'",
	noTags: "沒有標籤"});

config.macros.list.all.prompt = "依字母排序";
config.macros.list.missing.prompt = "被引用且內容空白的文章";
config.macros.list.orphans.prompt = "未被引用的文章";
config.macros.list.shadowed.prompt = "這些隱藏的文章已預設內容";
config.macros.list.touched.prompt = "自下載或新增後被修改過的文章"; 

merge(config.macros.closeAll,{
	label: "全部關閉",
	prompt: "關閉所有開啟中的 tiddler (編輯中除外)"});

merge(config.macros.permaview,{
	label: "引用連結",
	prompt: "可存取現有開啟之文章的連結位址"});

merge(config.macros.saveChanges,{
	label: "儲存變更",
	prompt: "儲存所有文章,產生新的版本",
	accessKey: "S"});

merge(config.macros.newTiddler,{
	label: "新增文章",
	prompt: "新增 tiddler",
	title: "新增文章",
	accessKey: "N"});

merge(config.macros.newJournal,{
	label: "新增日誌",
	prompt: "新增 jounal",
	accessKey: "J"});

merge(config.macros.options,{
	wizardTitle: "增訂的進階選項",
	step1Title: "增訂的選項儲存於瀏覽器的 cookies",
	step1Html: "<input type='hidden' name='markList'></input><br><input type='checkbox' checked='false' name='chkUnknown'>顯示未知選項</input>",
	unknownDescription: "//(未知)//",
	listViewTemplate: {
		columns: [
			{name: 'Option', field: 'option', title: "選項", type: 'String'},
			{name: 'Description', field: 'description', title: "說明", type: 'WikiText'},
			{name: 'Name', field: 'name', title: "名稱", type: 'String'}
			],
		rowClasses: [
			{className: 'lowlight', field: 'lowlight'}
			]}
	});

merge(config.macros.plugins,{
	wizardTitle: "擴充套件管理",
	step1Title: "- 已載入之套件",
	step1Html: "<input type='hidden' name='markList'></input>", // DO NOT TRANSLATE
	skippedText: "(此套件因剛加入,故尚未執行)",
	noPluginText: "未安裝套件",
	confirmDeleteText: "確認是否刪除此文章:\n\n%0",
	removeLabel: "移除 systemConfig 標籤",
	removePrompt: "移除 systemConfig 標籤",
	deleteLabel: "刪除",
	deletePrompt: "永遠刪除所選",

	listViewTemplate : {
		columns: [
			{name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'},
			{name: 'Tiddler', field: 'tiddler', title: "套件", type: 'Tiddler'},
			{name: 'Size', field: 'size', tiddlerLink: 'size', title: "大小", type: 'Size'},
			{name: 'Forced', field: 'forced', title: "強制執行", tag: 'systemConfigForce', type: 'TagCheckbox'},
			{name: 'Disabled', field: 'disabled', title: "停用", tag: 'systemConfigDisable', type: 'TagCheckbox'},
			{name: 'Executed', field: 'executed', title: "已載入", type: "Boolean", trueText: "是", falseText: "否"},
			{name: 'Startup Time', field: 'startupTime', title: "載入時間", type: 'String'},
			{name: 'Error', field: 'error', title: "載入狀態", type: 'Boolean', trueText: "錯誤", falseText: "正常"},
			{name: 'Log', field: 'log', title: "紀錄", type: 'StringList'}
			],
		rowClasses: [
			{className: 'error', field: 'error'},
			{className: 'warning', field: 'warning'}
			]}
	});

merge(config.macros.toolbar,{
	moreLabel: "其他",
	morePrompt: "顯示更多工具命令"});
	
merge(config.macros.refreshDisplay,{
	label: "刷新",
	prompt: "刷新此 TiddlyWiki 顯示"
	});
	
merge(config.macros.importTiddlers,{
	readOnlyWarning: "TiddlyWiki 於唯讀模式下,不支援導入文章。請由本機(file://)開啟 TiddlyWiki 文件",
	wizardTitle: "自其他檔案或伺服器導入文章",
	step1Title: "步驟一:指定伺服器或來源文件",
	step1Html: "指定伺服器類型:<select name='selTypes'><option value=''>選取...</option></select><br>請輸入網址或路徑:<input type='text' size=50 name='txtPath'><br>...或選擇來源文件:<input type='file' size=50 name='txtBrowse'><br><hr>...或選擇指定的饋入來源:<select name='selFeeds'><option value=''>選取...</option></select>",
	openLabel: "開啟",
	openPrompt: "開啟檔案或",
	openError: "讀取來源文件時發生錯誤",
	statusOpenHost: "正與伺服器建立連線",
	statusGetWorkspaceList: "正在取得可用之文章清單",
	step2Title: "步驟二:選擇工作區",
	step2Html: "輸入工作區名稱:<input type='text' size=50 name='txtWorkspace'><br>...或選擇工作區:<select name='selWorkspace'><option value=''>選取...</option></select>",
	cancelLabel: "取消",
	cancelPrompt: "取消本次導入動作",
	statusOpenWorkspace: "正在開啟工作區",
	statusGetTiddlerList: "正在取得可用之文章清單",
	step3Title: "步驟三:選擇欲導入之文章",
	step3Html: "<input type='hidden' name='markList'></input><br><input type='checkbox' checked='true' name='chkSync'>保持這些文章與伺服器的連結,便於同步後續的變更。</input><br><input type='checkbox' name='chkSave'>儲存此伺服器的詳細資訊於標籤為 'systemServer' 的文章名為:</input> <input type='text' size=25 name='txtSaveTiddler'>", 
	importLabel: "導入",
	importPrompt: "導入所選文章",
	confirmOverwriteText: "確定要覆寫這些文章:\n\n%0",
	step4Title: "步驟四:正在導入%0 篇文章",
	step4Html: "<input type='hidden' name='markReport'></input>", // DO NOT TRANSLATE
	doneLabel: "完成",
	donePrompt: "關閉",
	statusDoingImport: "正在導入文章 ...",
	statusDoneImport: "所選文章已導入",
	systemServerNamePattern: "%2 位於 %1",
	systemServerNamePatternNoWorkspace: "%1",
	confirmOverwriteSaveTiddler: "此 tiddler '%0' 已經存在。點擊「確定」以伺服器上料覆寫之,或「取消」不變更後離開",
	serverSaveTemplate: "|''Type:''|%0|\n|''網址:''|%1|\n|''工作區:''|%2|\n\n此文為自動產生紀錄伺服器之相關資訊。",
	serverSaveModifier: "(系統)",

	listViewTemplate: {
		columns: [
			{name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'},
			{name: 'Tiddler', field: 'tiddler', title: "文章", type: 'Tiddler'},
			{name: 'Size', field: 'size', tiddlerLink: 'size', title: "大小", type: 'Size'},
			{name: 'Tags', field: 'tags', title: "標籤", type: 'Tags'}
			],
		rowClasses: [
			]}
	});

merge(config.macros.sync,{
	listViewTemplate: {
		columns: [
			{name: 'Selected', field: 'selected', rowName: 'title', type: 'Selector'},
			{name: 'Tiddler', field: 'tiddler', title: "文章", type: 'Tiddler'},
			{name: 'Server Type', field: 'serverType', title: "伺服器類型", type: 'String'},
			{name: 'Server Host', field: 'serverHost', title: "伺服器主機", type: 'String'},
			{name: 'Server Workspace', field: 'serverWorkspace', title: "伺服器工作區", type: 'String'},
			{name: 'Status', field: 'status', title: "同步情形", type: 'String'},
			{name: 'Server URL', field: 'serverUrl', title: "伺服器網址", text: "View", type: 'Link'}
			],
		rowClasses: [
			],
		buttons: [
			{caption: "同步更新這些文章", name: 'sync'}
			]},
	wizardTitle: "將你的資料內容與外部伺服器與檔案同步",
	step1Title: "選擇欲同步的文章",
	step1Html: '<input type="hidden" name="markList"></input>', // DO NOT TRANSLATE
	syncLabel: "同步",
	syncPrompt: "同步更新這些文章",
	hasChanged: "已更動",
	hasNotChanged: "未更動",
	syncStatusList: {
		none: {text: "...", color: 'transparent'},
		changedServer: {text: "伺服器資料已更動", color: '#80ff80'},
		changedLocally: {text: "本機資料已更動", color: '#80ff80'},
		changedBoth: {text: "已同時更新本機與伺服器上的資料", color: '#ff8080'},
		notFound: {text: "伺服器無此資料", color: '#ffff80'},
		putToServer: {text: "已儲存更新資料至伺服器", color: '#ff80ff'},
		gotFromServer: {text: "已從伺服器擷取更新資料", color: '#80ffff'}
		}
	});

merge(config.macros.annotations,{
	});

merge(config.commands.closeTiddler,{
	text: "關閉",
	tooltip: "關閉本文"});

merge(config.commands.closeOthers,{
	text: "關閉其他",
	tooltip: "關閉其他文章"});

merge(config.commands.editTiddler,{
	text: "編輯",
	tooltip: "編輯本文",
	readOnlyText: "檢視",
	readOnlyTooltip: "檢視本文之原始內容"});

merge(config.commands.saveTiddler,{
	text: "完成",
	tooltip: "確定修改"});

merge(config.commands.cancelTiddler,{
	text: "取消",
	tooltip: "取消修改",
	warning: "確定取消對 '%0' 的修改嗎?",
	readOnlyText: "完成",
	readOnlyTooltip: "返回正常顯示模式"});

merge(config.commands.deleteTiddler,{
	text: "刪除",
	tooltip: "刪除文章",
	warning: "確定刪除 '%0'?"});

merge(config.commands.permalink,{
	text: "引用連結",
	tooltip: "本文引用連結"});

merge(config.commands.references,{
	text: "引用",
	tooltip: "引用本文的文章",
	popupNone: "本文未被引用"});

merge(config.commands.jump,{
	text: "捲頁",
	tooltip: "捲頁至其他已開啟的文章"});

merge(config.commands.syncing,{
	text: "同步",
	tooltip: "本文章與伺服器或其他外部檔案的同步資訊",
	currentlySyncing: "<div>同步類型:<span class='popupHighlight'>'%0'</span></"+"div><div>與伺服器:<span class='popupHighlight'>%1 同步</span></"+"div><div>工作區:<span class='popupHighlight'>%2</span></"+"div>", // Note escaping of closing <div> tag
	notCurrentlySyncing: "無進行中的同步動作",
	captionUnSync: "停止同步此文章",
	chooseServer: "與其他伺服器同步此文章:",
	currServerMarker: "\u25cf ",
	notCurrServerMarker: "  "});

merge(config.commands.fields,{
	text: "欄位",
	tooltip: "顯示此文章的擴充資訊",
	emptyText: "此文章沒有擴充欄位",
	listViewTemplate: {
		columns: [
			{name: 'Field', field: 'field', title: "擴充欄位", type: 'String'},
			{name: 'Value', field: 'value', title: "內容", type: 'String'}
			],
		rowClasses: [
			],
		buttons: [
			]}});

merge(config.shadowTiddlers,{
	DefaultTiddlers: "GettingStarted",
	GettingStarted: "使用此 TiddlyWiki 的空白範本之前,請先修改以下預設文章:\n* SiteTitle 及 SiteSubtitle:網站的標題和副標題,顯示於頁面上方<br />(在儲存變更後,將顯示於瀏覽器視窗的標題列)。\n* MainMenu:主選單(通常在頁面左側)。\n* DefaultTiddlers:內含一些文章的標題,可於載入TiddlyWiki 後的預設開啟。\n請輸入您的大名,作為所建立/ 編輯的文章署名:<<option txtUserName>>",
	MainMenu: "[[使用說明|GettingStarted]]\n\n\n^^~TiddlyWiki 版本:<<version>>\n© 2007 [[UnaMesa|http://www.unamesa.org/]]^^",
	OptionsPanel: "這些設定將暫存於瀏覽器\n請簽名<<option txtUserName>>\n (範例:WikiWord)\n\n <<option chkSaveBackups>> 儲存備份\n <<option chkAutoSave>> 自動儲存\n <<option chkRegExpSearch>> 正規式搜尋\n <<option chkCaseSensitiveSearch>> 區分大小寫搜尋\n <<option chkAnimate>> 使用動畫顯示\n----\n [[進階選項|AdvancedOptions]]",
	SiteTitle: "我的 TiddlyWiki",
	SiteSubtitle: "一個可重複使用的個人網頁式筆記本",
	SiteUrl: 'http://www.tiddlywiki.com/',
	SideBarOptions: '<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal " YYYY年0MM月0DD日" "日誌">><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel  "偏好設定 »" "變更 TiddlyWiki 選項">>',
	SideBarTabs: '<<tabs txtMainTab "最近更新" "依更新日期排序" TabTimeline "全部" "所有文章" TabAll "分類" "所有標籤" TabTags "更多" "其他" TabMore>>',
	StyleSheet: '[[StyleSheetLocale]]',
	TabMore: '<<tabs txtMoreTab "未完成" "內容空白的文章" TabMoreMissing "未引用" "未被引用的文章" TabMoreOrphans "預設文章" "已預設內容的隱藏文章" TabMoreShadowed>>'});

merge(config.annotations,{
	AdvancedOptions: "此預設文章可以存取一些進階選項。",
	ColorPalette: "此預設文章裡的設定值,將決定 ~TiddlyWiki 使用者介面的配色。",
	DefaultTiddlers: "當 ~TiddlyWiki 在瀏覽器中開啟時,此預設文章裡列出的文章,將被自動顯示。",
	EditTemplate: "此預設文章裡的 HTML template 將決定文章進入編輯模式時的顯示版面。",
	GettingStarted: "此預設文章提供基本的使用說明。",
	ImportTiddlers: "此預設文章提供存取導入中的文章。",
	MainMenu: "此預設文章的內容,為於螢幕左側主選單的內容",
	MarkupPreHead: "此文章的內容將加至 TiddlyWiki 文件的 <head> 段落的起始",
	MarkupPostHead: "此文章的內容將加至 TiddlyWiki 文件的 <head> 段落的最後",
	MarkupPreBody: "此文章的內容將加至 TiddlyWiki 文件的 <body> 段落的起始",
	MarkupPostBody: "此文章的內容將加至 TiddlyWiki 文件的 <body> 段落的最後,於 script 區塊之前",
	OptionsPanel: "此預設文章的內容,為於螢幕右側副選單中的選項面板裡的內容",
	PageTemplate: "此預設文章裡的 HTML template 決定的 ~TiddlyWiki 主要的版面配置",
	PluginManager: "此預設文章提供存取套件管理員",
	SideBarOptions: "此預設文章的內容,為於螢幕右側副選單中選項面板裡的內容",
	SideBarTabs: "此預設文章的內容,為於螢幕右側副選單中的頁籤面板裡的內容",
	SiteSubtitle: "此預設文章的內容為頁面的副標題",
	SiteTitle: "此預設文章的內容為頁面的主標題",
	SiteUrl: "此預設文章的內容須設定為文件發佈時的完整網址",
	StyleSheetColors: "此預設文章內含的 CSS 規則,為相關的頁面元素的配色。''勿修改此文'',請於 StyleSheet 中作增修。",
	StyleSheet: "此預設文章內容可包含 CSS 規則",
	StyleSheetLayout: "此預設文章內含的 CSS 規則,為相關的頁面元素的版面配置。''勿修改此文'',請於 StyleSheet 中作增修。",
	StyleSheetLocale: "此預設文章內含的 CSS 規則,可依翻譯語系做適當調整",
	StyleSheetPrint: "此預設文章內含的 CSS 規則,用於列印時的樣式",
	TabAll: "此預設文章的內容,為於螢幕右側副選單中的「全部」頁籤的內容",
	TabMore: "此預設文章的內容,為於螢幕右側副選單中的「更多」頁籤的內容",
	TabMoreMissing: "此預設文章的內容,為於螢幕右側副選單中的「未完成」頁籤的內容",
	TabMoreOrphans: "此預設文章的內容,為於螢幕右側副選單中的「未引用」頁籤的內容",
	TabMoreShadowed: "此預設文章的內容,為於螢幕右側副選單中的「預設文章」頁籤的內容",
	TabTags: "此預設文章的內容,為於螢幕右側副選單中的「分類」頁籤的內容",
	TabTimeline: "此預設文章的內容,為於螢幕右側副選單中的「最近更新」頁籤的內容",
	ViewTemplate: "此預設文章裡的 HTML template 決定文章顯示的樣子"
	});
//}}}
/***
|Name|ShowUpdatesPlugin|
|Created by|SaqImtiaz|
|Version|0.2 |
|Requires|~TW2.x|
!!!Description:
Allows you to list tiddlers that have changed since the users last visit. You can list only all changed tiddlers, or filter them to only show tiddlers that have or do not have a specific tag. By default a simple list of the titles of changed tiddlers is created. However, using an extremely versatile syntax you can provide a custom template for the generated text.

!!!Installation:
Copy the contents of this tiddler to your TW, tag with systemConfig, save and reload your TW.

!!!Syntax:
{{{<<showUpdates>>}}}
additional optional params:
{{{<showUpdates excludeTag:TagToExclude onlyTag:TagToList maxEntries:10 write:CustomWriteParameter >>}}}
excludeTag: ~TagToExclude
onlyTag: ~TagToList
maxEntries: max number of entries displayed when there are no updates. (default is 10, which can be changed in the config.macros.showUpdates.settings part of the code)
write: if a write parameter is not provided, an un-numbered list of the updates is generated. Alternatively, you can specify a custom 'template' for the text generated. The syntax for the write parameter is identical to that of the forEachTiddler macro. Additonal documentation on this syntax will be provided soon.
Some of the variables available in the write parameter are 'index', 'count' and 'lastVisit' where lastVisit is the date of the last visit in the format YYYYMMDDHHMM. Also areUpdates is a boolean that is true if there are new updates since the users last visit.

!!!To Do:
*refactor code to facilitate translations
*a streamlined version without the custom write parameter


!!!Code
***/
//{{{
window.lewcidLastVisit = '';
window.old_lewcid_whatsnew_restart = window.restart;
window.restart = function()
{
        if(config.options.txtLastVisit)
                 lewcidLastVisit= config.options.txtLastVisit;
        config.options.txtLastVisit = (new Date()).convertToYYYYMMDDHHMM();
        saveOptionCookie('txtLastVisit');
        window.old_lewcid_whatsnew_restart();
}

TiddlyWiki.prototype.lewcidGetTiddlers = function(field,excludeTag,includeTag,updatesOnly)
{
              var results = [];
              this.forEachTiddler(function(title,tiddler)
                      {
                      if(excludeTag == undefined || !tiddler.isTagged(excludeTag))
                                    if(includeTag == undefined ||  tiddler.isTagged(includeTag))
                                            if ( updatesOnly == false || tiddler.modified.convertToYYYYMMDDHHMM()>lewcidLastVisit)
                                                  results.push(tiddler);
                      });
              if(field)
                  results.sort(function (a,b) {if(a[field] == b[field]) return(0); else return (a[field] < b[field]) ? -1 : +1; });
              return results;
}

config.macros.showUpdates={};
config.macros.showUpdates.settings =
{
         maxEntries: 10  //max items to show, if there are no updates since last visit
}

config.macros.showUpdates.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
          var args = paramString.parseParams("list",null,true);
          var write = getParam(args, "write", undefined);
          var onlyTag = getParam(args, "onlyTag", undefined);
          var excludeTag = getParam(args, "excludeTag", undefined);
          var sortBy = "modified";
          var maxEntries = getParam(args,"maxEntries",this.settings.maxEntries);

          if (lewcidLastVisit) 
                {var tiddlers = store.lewcidGetTiddlers(sortBy,excludeTag,onlyTag,true);
                 var areUpdates = tiddlers.length>0? true:false;}

          //if (!lewcidLastVisit)
          //     {var countLine = "!!最近的更新:";
                  var tiddlers = store.lewcidGetTiddlers(sortBy,excludeTag,onlyTag,false);
                  var areUpdates = false;
          //     }
          //else if (tiddlers.length == 0)
          //     {var countLine = "!!@@color:red;上次拜訪後, 沒有任何更新 " + (Date.convertFromYYYYMMDDHHMM(lewcidLastVisit)).formatString(" (DD/MM/YY)") + "@@\n!!最近的更新:";
         //      var tiddlers = store.lewcidGetTiddlers(sortBy,excludeTag,onlyTag,false);}
         // else
         //      {var countLine ="!!@@ 自從上次拜訪後, 共有 "+ tiddlers.length +" 更新 " + (Date.convertFromYYYYMMDDHHMM(lewcidLastVisit)).formatString(" (DD/MM/YY)") + "@@";}

          tiddlers = tiddlers.reverse();
          var lastVisit = lewcidLastVisit? lewcidLastVisit:undefined;
          var count = areUpdates == true? tiddlers.length : maxEntries;
          var sp = createTiddlyElement(place,"span","showUpdates");
          if (write==undefined)
                 {
                  //wikify(countLine,sp);
                  var list = createTiddlyElement(sp,"ul");
                  for (var i = 0; i < count; i++)
                          {
                           var tiddler = tiddlers[i];
                           createTiddlyLink(createTiddlyElement(list,"li"), tiddler.title, true);
                          }
                 }
          else
                {
                 var list = '';
                 for (var index = 0; index < count; index++) {
                 var tiddler = tiddlers[index];
                 list += eval(write); }
                 wikify(list, sp);
                }
}
//}}}
/***
|''巨集名稱:''|toBalaAjax|
|''版本:''|2.1 (2008-06-28)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''| |
***/

//{{{
config.macros.toBalaAjax={
	
	editLabel: "編輯網頁",
	editTip: "編輯網頁",
        saveLabel: "儲存網頁",
	saveTip: "儲存網頁",
        openLabel: "檢視網頁",
	openTip: "檢視網頁",
        cancelLabel: "取消編輯",
	cancelTip: "取消編輯",
    
	GUIEditButtonOnclick: function(e,xtiddler,xbox,xfname,xx,yy) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }

            removeChildren(xbox);

            var boxtool = createTiddlyElement(xbox,"div",null,"toBalaFileToolBar",null,null);
            var boxtext = createTiddlyElement(xbox,"textarea",null,null,null,null);
            wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+xfname+"</nowiki>@@ ",boxtool);

            createTiddlyButton(boxtool,this.saveLabel,this.saveTip,
                            function(e) { config.macros.toBalaAjax.GUISaveButtonOnclick(e,xtiddler,xbox,xfname,boxtext,xx,yy); },
                            "toBalaFileSave",null,null);
	    createTiddlyButton(boxtool,this.cancelLabel,this.cancelTip,
                            function(e) { config.macros.toBalaAjax.GUICancelButtonOnclick(e,xtiddler,xbox,xfname,xx,yy); },
                            "toBalaFileCancel",null,null);

            // alert(xtitle+":"+xx+":"+yy);
            boxtext.setAttribute("rows",20);
            boxtext.setAttribute("cols",88);
            boxtext.value = xtiddler.text.substring(xx,yy);
        },

	GUISaveButtonOnclick: function(e,xtiddler1,xbox1,xfname1,boxtext1,xx1,yy1) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }
 
            removeChildren(xbox1);
            var xtext=boxtext1.value;
            if (config.browser.isIE) {              
               xtext=xtext.replace(/\r/g,"");   // 請看最後的註解
            }
            var toptext=xtiddler1.text.substring(0,xx1);
            var bottomtext=xtiddler1.text.substring(yy1);
            xtext = (xtext.charAt(xtext.length-1) == "\n" ? xtext : xtext+"\n");
            xtiddler1.text=toptext+xtext+bottomtext;

            story.refreshTiddler(xtiddler1.title,null,true);
            saveChanges(false);              // 參數 false, 代表不管 Dirty 與否, 均要執行存檔動作

            var baseDIR = getLocalPath(document.URL);
  
            if (config.browser.isWindows) {
                var baseDIR = baseDIR.replace(/\//g,"");
                var x = baseDIR.lastIndexOf("\\");
             } else {
                var x = baseDIR.lastIndexOf("/");
             }

            baseDIR = baseDIR.substr(0,x+1);

            var s = saveFile(baseDIR+ (config.browser.isWindows ? xfname1 : xfname1.replace(/\\/g,"\/")), 
                                          convertUnicodeToUTF8(boxtext1.value));
            if (!s) {
               alert("存檔失敗");
            }
        },

	GUICancelButtonOnclick: function(e,xtiddler1,xbox1,xfname1,xx1,yy1) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }

            removeChildren(xbox1);

            var boxtool = createTiddlyElement(xbox1,"div",null,"toBalaFileToolBar",null,null);
            wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+xfname1+"</nowiki>@@ ",boxtool);

	    createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaAjax.GUIEditButtonOnclick(e,xtiddler1,xbox1,xfname1,xx1,yy1);},
                            "toBalaFileEdit",null,null);

	    createTiddlyButton(boxtool,this.openLabel,this.openTip,
                            function(e) { config.macros.toBalaAjax.openHTML(e,params[0],xwidth,xheight);},
                            "toBalaFileEdit",null,null);

             var boxarea = createTiddlyElement(xbox1,"div",null,null,null,null);
	     wikify("{{{\n"+xtiddler1.text.substring(xx1,yy1-1)+"\n}}}",boxarea);
        },

        openHTML: function(ev,xf,xw,xh) {

               if (config.browser.isIE) {
                  window.event.cancelBubble=true;
               } else {  
                  ev.cancelBubble=true;   
               if (ev.stopPropagation)  
                  ev.stopPropagation();
               }

               // 將視窗置中
               var winl = (screen.width-xw)/2;
               var wint = (screen.height-xh)/2;
               if (winl < 0) winl = 0;
               if (wint < 0) wint = 0;
               var settings = 'scrollbars=yes, resizable=yes, height='  + xh +  ', width=' + xw  + ',top='  + wint  + ',left='  + winl;

               xf=xf.replace(/\\/mg,"/");

               // alert(xf+":"+settings);
               var xwin=window.open(xf,"HTMLWIN",settings);
               xwin.window.focus();
        },

	handler : function(place,macroName,params,wikifier,paramString,tiddler){

                if (!params[0]) {
                  alert("請給檔名");
                  return;
                } 

                var xwidth = params[1] || 550;
                var xheight = params[2] || 400;

		var xtext=store.getTiddlerText(tiddler.title);
                var x1=xtext.indexOf("/"+"/"+"/"+"%" + params[0]);

                // 自動產生 TiddlyWiki 備註
                if (x1 == -1) { 
                   xtext=xtext+"\n\n/"+"/"+"/"+"%" + params[0] + "\n" + "/"+"/"+"%"+"/";
                   tiddler.text=xtext; 
                   story.refreshTiddler(tiddler.title,null,true); // 這個 Tiddler 會重新顯示, 也就是 handler 會再被執行一次
                   //saveChanges(false);
                 }
                var x2=xtext.indexOf("/"+"/"+"%"+"/",x1);
                x1=x1+params[0].length+5;

		var box = createTiddlyElement(place,"div",tiddler.title+"-"+x1,"toBalaFile",null,null);
                var boxtool = createTiddlyElement(box,"div",null,"toBalaFileToolBar",null,null);
                wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+params[0]+"</nowiki>@@ ",boxtool);

                var boxtext = createTiddlyElement(box,"div",null,null,null,null);
		wikify("{{{\n"+xtext.substring(x1,x2-1)+"\n}}}",boxtext);

                if (readOnly) {
                   return;
                }
		createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaAjax.GUIEditButtonOnclick(e,tiddler,box,params[0],x1,x2);},
                            "toBalaFileEdit",null,null);

		createTiddlyButton(boxtool,this.openLabel,this.openTip,
                            function(e) { config.macros.toBalaAjax.openHTML(e,params[0],xwidth,xheight);},
                            "toBalaFileEdit",null,null);
	}		
};

/*
HTML 的 textarea 標籤, 對於換行在不同的瀏覽器有不同的處理方式

As you may know, the humble line break actually has three forms depending on which operating system is doing the breaking. On Unix machines, a single newline character ‘\n’ does the job. On Macs, a carriage return ‘\r’ is used. DOS and Windows use both: ‘\r\n’. It’s one of those relatively subtle issues that can bite you hard if you don’t know what to look out for.
*/

//}}}
{{item1{使用格式}}}
{{{
<<toBalaAjax  "ajax\html\testAjax.htm">>
}}}

{{item1{實作範例}}}
<<toBalaAjax "ajax\html\testAjax.htm">>

///%ajax\html\testAjax.htm
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf8">
</head>

<body>
<h2 align=center>顯示網頁載入時間的警告視窗</h2>
<hr>

<script>
today = new Date();			// 產生日期物件
hour = today.getHours();		// 取得時數
minute = today.getMinutes();		// 取得分數
second = today.getSeconds();		// 取得秒數
string = "網頁載入時間是"+hour+"點"+minute+"分"+second+"秒";	// 連接字串
</script>
<a href="javascript:alert(string)">網頁載入時間</a>

<hr>
</body>
</html>
//%/
<<toBalaAjax "ajax\AjaxCall.htm" "700" "450">>

///%ajax\AjaxCall.htm
<!-- 
程式名稱 : AjaxCall.html
程式描述 : Call XMLHTTP Object
適用瀏覽器 : Firefox 2.0,IE 5.5
參考文件 : 
-->
<html>
	
<head>
	
<meta http-equiv="Expires" content="0">
<meta http-equiv="Content-Type" content="text/html; charset=utf8">

<script>
var xmlhttp
function show(){
 
 if (window.XMLHttpRequest) {
    netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
    xmlhttp = new XMLHttpRequest();    
 }
 else if (window.ActiveXObject){ 
    try {
          xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
         }
    catch (e){
      try{
         xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
      catch (e){}
    }
 }

 xmlhttp.open(document.getElementById("c").value,document.getElementById("u").value,false);
 xmlhttp.send("");
 if (parseInt(xmlhttp.status)>300){
     alert(xmlhttp.status);
 }
 else {
  document.getElementById("h").innerHTML=xmlhttp.getAllResponseHeaders();
  
  if (xmlhttp.getResponseHeader("Content-Type") == "text/xml"){
  	 xmlobj=xmlhttp.responseXML;
     document.getElementById("x").innerHTML=xmlobj.getElementsByTagName('app')[0].firstChild.nodeValue;
  }
  else{
  	 document.getElementById("x").innerHTML="";
     var testFrame = document.getElementById("myFrame");
     var doc = testFrame.contentDocument;
     if (doc == undefined || doc == null)
        doc = testFrame.contentWindow.document;
     doc.open();
     doc.write(xmlhttp.responseText);
	 doc.close(); 
  }  
 }
}
</script>
</head>

<style type="text/css">
body {
 background-color:white;
}
</style>

<body>
<h2>Ajax 測試程式 (使用本機的瀏覽器以 "開啟檔案" 方式執行)</h2>
<hr>
Method: <input id="c" value="GET" style="width: 100px;" type="text"><span> (要大寫) </span><br> 
URL: <input style="width: 250px;" id="u" value="http://" type="text"><br>

<button onclick="show();">傳送命令</button>
<hr>

<b>Response Header</b>
<pre id="h"></pre>

<b>Response XML</b>
<pre id="x"></pre>

<b>Response HTML</b><br>
<iframe id="myFrame" height="30%" width="100%"></iframe>

</body>
</html>

<!--
HTTP Methods
-------------
HTTP defines eight methods (sometimes referred to as "verbs") indicating the desired 
action to be performed on the identified resource.

HEAD
    Asks for the response identical to the one that would correspond to a GET request, 
    but without the response body. This is useful for retrieving meta-information 
	written in response headers, without having to transport the entire content.
GET
    Requests a representation of the specified resource. By far the most common method
	used on the Web today. Should not be used for operations that cause side-effects 
	(using it for actions in web applications is a common mis-use). See 'safe methods' 
	below.
POST
    Submits data to be processed (e.g. from an HTML form) to the identified resource. 
	The data is included in the body of the request. This may result in the creation 
	of a new resource or the updates of existing resources or both.
PUT
    Uploads a representation of the specified resource.
DELETE
    Deletes the specified resource.
TRACE
    Echoes back the received request, so that a client can see what intermediate 
	servers are adding or changing in the request.
OPTIONS
    Returns the HTTP methods that the server supports. This can be used to check the 
	functionality of a web server.
CONNECT
    For use with a proxy that can change to being an SSL tunnel.


WebDAV added the following methods to HTTP:

    * PROPFIND — Used to retrieve properties, persisted as XML, from a resource. 
	             It is also overloaded to allow one to retrieve the collection 
				 structure (a.k.a. directory hierarchy) of a remote system.
    * PROPPATCH — Used to change and delete multiple properties on a resource 
	              in a single atomic act.
    * MKCOL — Used to create collections (a.k.a. directory).
    * COPY — Used to copy a resource from one URI to another.
    * MOVE — Used to move a resource from one URI to another.
    * LOCK — Used to put a lock on a resource. WebDAV supports both shared and 
	         exclusive locks.
    * UNLOCK — To remove a lock from a resource.

-->
//%/
/***
|''巨集名稱:''|toBalaApp|
|''版本:''|2.1 (2008-10-2)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''| |
***/
//{{{
config.macros.toBalaApp={
       mode:"open",

       handler : function(place,macroName,params,wikifier,paramString,tiddler){
                if (!params[0]) {
                  alert("請給檔名");
                  return;
                } 
		createTiddlyButton(place,"應用模式","應用模式", function(e) { config.macros.toBalaApp.onClick(params[0]); } );

                /* 下式的寫法, 在執行 handler 的同時也會執行 onClick, 這樣的執行方式不對, 所以請使用上式
                     createTiddlyButton(place,"應用模式","應用模式",this.onClick(params[0]));
                */ 
	},
       onClick : function(xapp) {
            // alert(this.mode+":"+xapp);
            if (this.mode=="open"){
               this.mode="close";
               document.getElementById("displayArea").style.display="none";
               document.getElementById("mainMenu").style.display="none";
               document.getElementById("ApplicationArea").style.display="block";
               document.getElementById("ApplicationArea").style.width="99.6%";
               document.getElementById("ApplicationArea").style.height=(window.screen.availHeight-200)+"px";
               document.getElementById("ApplicationArea").src=xapp;               
               return false;
            } else {
               this.mode="open";
               document.getElementById("displayArea").style.display="block";
               document.getElementById("mainMenu").style.display="block";
               document.getElementById("ApplicationArea").style.display="none";
               document.getElementById("ApplicationArea").src="";   
               return  false;
            }
        }	
};

//}}}
/***
|''巨集名稱:''|toBalaBackup|
|''版本:''|1.0 (2008-09-12)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0|
|''使用文件''| &lt;&lt;toBalaBackup '備份檔名'  '樹幹名'  '文章,文章,文章'&gt;&gt;|
***/

//{{{
// 自定的巨集變數, 開頭前三個字如為 txt, 結合 option 巨集會以文字欄處理, 前三個字如為 chk, 結合 option 巨集會以 checkbox 欄處理
config.options.txtBalaBackupFileName = config.options.txtBalaBackupFileName ? config.options.txtBalaBackupFileName : "toBalaBackup.html";
config.options.txtBalaTreeBody = config.options.txtBalaTreeBody ? config.options.txtBalaTreeBody : "";
config.options.txtBalaBackupOthers = config.options.txtBalaBackupOthers ? config.options.txtBalaBackupOthers : "首頁,MainMenu,SiteTitle,SiteSubtitle,00-控制台,StyleSheet";

config.macros.toBalaBackup = {};
config.macros.toBalaBackup.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  if (readOnly) {
     return;
  }

  if (!params[0] && config.options.txtBalaBackupFileName == "") {
     alert("請給檔名");
     return;
  }
  var tbName = config.options.txtBalaBackupFileName != "" ? config.options.txtBalaBackupFileName : params[0];   // 備份檔名
  var tbTag = config.options.txtBalaTreeBody != "" ? config.options.txtBalaTreeBody : params[1] ;            // 備份主標籤
  var tbTD = config.options.txtBalaBackupOthers != "" ? config.options.txtBalaBackupOthers : params[2];      // 其它備份文章
  var label = params[3] || "備份資訊樹文章";
  var tooltip = params[4] || "備份資訊樹文章 : " + tbName;

  createTiddlyButton(place, label, tooltip,
       function(e) { config.macros.toBalaBackup.save(e, tbName, tbTag, tbTD); },
       null, null, null);
}

config.macros.toBalaBackup.save = function(ev,xfname,xtag, xtd) {

  if (config.browser.isIE) {
     window.event.cancelBubble=true;
  } else {  
     ev.cancelBubble = true;   
     if (ev.stopPropagation)  
        ev.stopPropagation();
  }

  var baseDIR = getLocalPath(document.URL);
  //alert(baseDIR);
  
   if (config.browser.isWindows) {
      var baseDIR = baseDIR.replace(/\//g,"");
      var x = baseDIR.lastIndexOf("\\");
   } else {
      var x = baseDIR.lastIndexOf("/");
   }

   baseDIR = baseDIR.substr(0,x+1);
   //alert(baseDIR);

   toBala.AllTiddlers = "";
   // 呼叫 toBalaLIB 的 getMainTree() 方法, 取出資訊樹的樹幹及所有文章抬頭
   if (xtag!="") {
      var tbTempArr = toBala.getMainTree(xtag);

      for(var i=0; i<tbTempArr.length; ++i)
           toBala.TagDigg(tbTempArr[i]);
   }

   // 取出資訊樹所有文章的 DIV 內容
   var tbText='<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /><body>\n<div id="storeArea">';
   if (toBala.AllTiddlers!="") {
      var tbArr = toBala.AllTiddlers.split(",");
      for(i=0;i<tbArr.length;++i){
         if (tbArr[i])
            tbText = tbText+ "\n" + toBala.getTiddlerDIV(tbArr[i]);
      }
   }
   // 取出指定文章的 DIV 內容
   if (xtd!=""){
      tbArr = xtd.split(",");
      for(i=0;i<tbArr.length;++i)
          tbText = tbText+ "\n" + toBala.getTiddlerDIV(tbArr[i]);
   }
   tbText = tbText + "</div></body></html>";

   var s = saveFile(baseDIR+ (config.browser.isWindows?xfname:xfname.replace(/\\/g,"\/")), convertUnicodeToUTF8(tbText));
   if (s) {
      saveChanges(true);
      alert("備份完成");
   } else {
      alert("備份失敗");
   }
}
//}}}
config.options.chkAutoSave=false;
config.options.chkSaveBackups=false;
config.options.txtUserName="toBala";
config.options.txtMaxEditRows=50;
config.options.chkHttpReadOnly=true;

config.options.chkHideTabsBarWhenSingleTab=true;

config.options.chkDisableWikiLinks=true;
config.options.chkAllowLinksFromShadowTiddlers=true;
config.options.chkDisableNonExistingWikiLinks=true;
/***
|''巨集名稱:''|toBalaCoreBackup|
|''版本:''|1.0 (2008-09-12)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0|
|''使用文件''| &lt;&lt;toBalaCoreBackup '備份檔名' '文章,文章,文章'&gt;&gt;|
***/

//{{{
// 自定的巨集變數, 開頭前三個字如為 txt, 結合 option 巨集會以文字欄處理, 前三個字如為 chk, 結合 option 巨集會以 checkbox 欄處理
config.options.txtBalaCoreBackupFileName = config.options.txtBalaCoreBackupFileName ? config.options.txtBalaCoreBackupFileName : "toBalaMacro.html";
config.options.txtBalaCoreBackupOthers = config.options.txtBalaCoreBackupOthers ? config.options.txtBalaCoreBackupOthers : "";

config.macros.toBalaCoreBackup = {};
config.macros.toBalaCoreBackup.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  if (readOnly) {
     return;
  }

  if (!params[0] && config.options.txtBalaCoreBackupFileName == "") {
     alert("請給檔名");
     return;
  }
  var tbName = params[0] || config.options.txtBalaCoreBackupFileName;          // toBala 巨集備份檔名
  var tbTD = params[1] || config.options.txtBalaCoreBackupOthers;            // 其它備份文章
  var label = params[2] || "備份 toBala 巨集";
  var tooltip = params[3] || "備份 toBala 巨集 : " + tbName;

  createTiddlyButton(place, label, tooltip,
       function(e) { config.macros.toBalaCoreBackup.save(e, tbName, tbTD); },
       null, null, null);
}

config.macros.toBalaCoreBackup.save = function(ev,xfname, xtd) {

  if (config.browser.isIE) {
     window.event.cancelBubble=true;
  } else {  
     ev.cancelBubble = true;   
     if (ev.stopPropagation)  
        ev.stopPropagation();
  }

  var baseDIR = getLocalPath(document.URL);
  //alert(baseDIR);
  
   if (config.browser.isWindows) {
      var baseDIR = baseDIR.replace(/\//g,"");
      var x = baseDIR.lastIndexOf("\\");
   } else {
      var x = baseDIR.lastIndexOf("/");
   }

   baseDIR = baseDIR.substr(0,x+1);
   // alert(baseDIR);

   // 取出所有 toBala 巨集的 DIV 內容
   var tbT2 = store.getTaggedTiddlers("toBala");
   var tbText='<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /></head>';
   tbText = tbText + '<body>\n<div id="storeArea">';
   for (var i=0; i<tbT2.length; ++i) {
        tbText = tbText+ "\n" + toBala.getTiddlerDIV(tbT2[i].title);
   }

   // 取出指定文章的 DIV 內容
   if (xtd!=""){
      tbArr = xtd.split(",");
      for(i=0;i<tbArr.length;++i)
          tbText = tbText+ "\n" + toBala.getTiddlerDIV(tbArr[i]);
   }
   tbText = tbText + "</div></body></html>";

   var s = saveFile(baseDIR+ (config.browser.isWindows?xfname:xfname.replace(/\\/g,"\/")), convertUnicodeToUTF8(tbText));
   if (s) {
      saveChanges(true);
      alert("備份完成");
   } else {
      alert("備份失敗");
   }
}
//}}}
/***
|''巨集名稱:''|toBalaFile|
|''版本:''|1.0 (2008-05-09)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''||
***/

//{{{
config.macros.toBalaFile={
	
	editLabel: "編輯",
	editTip: "編輯",
        saveLabel: "儲存",
	saveTip: "儲存",
        cancelLabel: "取消",
	cancelTip: "取消",
    
	GUIEditButtonOnclick: function(e,xtiddler,xbox,xfname,xx,yy) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }

            removeChildren(xbox);

            var boxtool = createTiddlyElement(xbox,"div",null,"toBalaFileToolBar",null,null);
            var boxtext = createTiddlyElement(xbox,"textarea",null,null,null,null);
            wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+xfname+"</nowiki>@@ ",boxtool);

            createTiddlyButton(boxtool,this.saveLabel,this.saveTip,
                            function(e) { config.macros.toBalaFile.GUISaveButtonOnclick(e,xtiddler,xbox,xfname,boxtext,xx,yy); },
                            "toBalaFileSave",null,null);
	    createTiddlyButton(boxtool,this.cancelLabel,this.cancelTip,
                            function(e) { config.macros.toBalaFile.GUICancelButtonOnclick(e,xtiddler,xbox,xfname,xx,yy); },
                            "toBalaFileCancel",null,null);

            // alert(xtitle+":"+xx+":"+yy);
            boxtext.setAttribute("rows",20);
            boxtext.setAttribute("cols",88);
            boxtext.value = xtiddler.text.substring(xx,yy);
        },

	GUISaveButtonOnclick: function(e,xtiddler1,xbox1,xfname1,boxtext1,xx1,yy1) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }
 
            removeChildren(xbox1);
            var xtext=boxtext1.value;
            if (config.browser.isIE) {              
               xtext=xtext.replace(/\r/g,"");   // 請看最後的註解
            }
            var toptext=xtiddler1.text.substring(0,xx1);
            var bottomtext=xtiddler1.text.substring(yy1);
            xtext = (xtext.charAt(xtext.length-1) == "\n" ? xtext : xtext+"\n");
            xtiddler1.text=toptext+xtext+bottomtext;

            story.refreshTiddler(xtiddler1.title,null,true);
            saveChanges(false);              // 參數 false, 代表不管 Dirty 與否, 均要執行存檔動作

            var baseDIR = getLocalPath(document.URL);
  
            if (config.browser.isWindows) {
                var baseDIR = baseDIR.replace(/\//g,"");
                var x = baseDIR.lastIndexOf("\\");
             } else {
                var x = baseDIR.lastIndexOf("/");
             }

            baseDIR = baseDIR.substr(0,x+1);

            var s = saveFile(baseDIR+ (config.browser.isWindows ? xfname1 : xfname1.replace(/\\/g,"\/")), 
                                          convertUnicodeToUTF8(boxtext1.value));
            if (!s) {
               alert("存檔失敗");
            }
        },

	GUICancelButtonOnclick: function(e,xtiddler1,xbox1,xfname1,xx1,yy1) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }

            removeChildren(xbox1);

            var boxtool = createTiddlyElement(xbox1,"div",null,"toBalaFileToolBar",null,null);
            wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+xfname1+"</nowiki>@@ ",boxtool);

	    createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaFile.GUIEditButtonOnclick(e,xtiddler1,xbox1,xfname1,xx1,yy1);},
                            "toBalaFileEdit",null,null);

             var boxarea = createTiddlyElement(xbox1,"div",null,null,null,null);
	     wikify("{{{\n"+xtiddler1.text.substring(xx1,yy1-1)+"\n}}}",boxarea);
        },

	handler : function(place,macroName,params,wikifier,paramString,tiddler){

                if (!params[0]) {
                  alert("請給檔名");
                  return;
                } 

		var xtext=store.getTiddlerText(tiddler.title);
                var x1=xtext.indexOf("/"+"/"+"/"+"%" + params[0]);

                // 自動產生 TiddlyWiki 備註
                if (x1 == -1) { 
                   xtext=xtext+"\n\n/"+"/"+"/"+"%" + params[0] + "\n" + "/"+"/"+"%"+"/";
                   tiddler.text=xtext; 
                   story.refreshTiddler(tiddler.title,null,true); // 這個 Tiddler 會重新顯示, 也就是 handler 會再被執行一次
                   //saveChanges(false);
                 }
                var x2=xtext.indexOf("/"+"/"+"%"+"/",x1);
                x1=x1+params[0].length+5;

		var box = createTiddlyElement(place,"div",tiddler.title+"-"+x1,"toBalaFile",null,null);
                var boxtool = createTiddlyElement(box,"div",null,"toBalaFileToolBar",null,null);
                wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+params[0]+"</nowiki>@@ ",boxtool);

                var boxtext = createTiddlyElement(box,"div",null,null,null,null);
		wikify("{{{\n"+xtext.substring(x1,x2-1)+"\n}}}",boxtext);

                if (readOnly) {
                   return;
                }
		createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaFile.GUIEditButtonOnclick(e,tiddler,box,params[0],x1,x2);},
                            "toBalaFileEdit",null,null);
	}		
};

/*
HTML 的 textarea 標籤, 對於換行在不同的瀏覽器有不同的處理方式

As you may know, the humble line break actually has three forms depending on which operating system is doing the breaking. On Unix machines, a single newline character ‘\n’ does the job. On Macs, a carriage return ‘\r’ is used. DOS and Windows use both: ‘\r\n’. It’s one of those relatively subtle issues that can bite you hard if you don’t know what to look out for.
*/

//}}}
在文章中使用 toBalaFile 巨集, 可將巨集中所編輯的文字, 存入指定的檔案, 請看以下使用格式
{{{
<<toBalaFile "ajax\html\hello.htm">>

此巨集以 UTF-8 編碼, 儲存檔文字到檔案
}}}

__{{op1{實作範例}}}__
<<toBalaFile "ajax\html\hello.htm">>

///%ajax\html\hello.htm
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf8">
</head>

<body>
<h2 align=center>利用 JavaScript 來印出 "Hello World!"</h2>
<hr>
<script language="javascript">
	str = "Hello World!";
	document.write(str);
</script>
<hr>
</body>
</html>
//%/
{{item1{說明}}}
{{{

<<toBalaFile "檔名">>

}}}
{{item1{範例}}}
<<toBalaFile "xml\abc.xml">>


///%xml\abc.xml
<?xml version='1.0'?>
<root>
  <marble color="red"/>
  <marble color='red'/>
</root> 
//%/
/***
|''巨集名稱:''|toBalaFlashPlayer|
|''版本:''|1.0 (2008-03-06)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''| |
***/
//{{{
config.macros.toBalaFlashPlayer = {};

config.macros.toBalaFlashPlayer.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  var xname = params[0] || tiddler.title;
  var label = params[1] || "撥放 " + xname;
  var xwidth = params[2] || 600;
  var xheight = params[3] || 450;

  createTiddlyButton(place, label, label,
       function(e) { config.macros.toBalaFlashPlayer.show(e, xname, xwidth, xheight); },
       null, null, null);
}

config.macros.toBalaFlashPlayer.show = function(ev,fname,xw,xh) {

  if (config.browser.isIE) {
     window.event.cancelBubble=true;
  } else {  
     ev.cancelBubble = true;   
     if (ev.stopPropagation)  
        ev.stopPropagation();
  }

  if (config.browser.isIE)
     var URLtext = document.URL.replace(/\\/g,"\/");
  else 
     var URLtext = document.URL;
  //alert(URLtext);

  var x = URLtext.lastIndexOf("/");
  var baseDIR = URLtext.substr(0,x);
  var jsDIR = '<script type="text/javascript" src="' + baseDIR + '/jslib/swfobject/swfobject.js"></script>'
  //alert(jsDIR);

  var generator=window.open('','name','height=' + xh +',width=' + xw);
  generator.document.open();
  generator.document.write('<html><head><title>toBala Flash Player</title>');
  generator.document.write(jsDIR);
  generator.document.write('</head><body>');
  generator.document.write('<div id="flashTag" style="width:'+(xw-5)+'px;height:'+(xh-5)+'px;overflow:auto"></div>');
  generator.document.write('<script type="text/javascript">');
  generator.document.write('var xo = new SWFObject("' + baseDIR + '/' + fname + '","mymovie","'+(xw-5)+'","'+(xh-5)+'","8", "#336699");');
  //generator.document.write('xo.addParam("wmode", "transparent");');
  generator.document.write('xo.write("flashTag");');
  generator.document.write('</script>');
  generator.document.write('</body></html>');
  generator.document.close();

}
//}}}
使用 toBalaFlashPlayer 巨集, 來撥放指定的 Flash 檔, 命令格式如下 :
{{{
<<toBalaFlashPlayer "movie/infotree.swf" "" "820" "610">>
}}}

{{item1{實作範例 : winzip 的安裝}}}

<<toBalaFlashPlayer "movie/winzip.swf" "" "800" "580">>
/***
|''巨集名稱:''|toBalaHTML|
|''版本:''|1.0 (2008-03-18)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''|&lt;&lt;toBalaHTML  title  filename  label  tooltip  width  height&gt;&gt; |
***/

//{{{
config.macros.toBalaHTML = {};

config.macros.toBalaHTML.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  var title = params[0] || tiddler.title;
  var xfname = params[1] || "";          // 外部檔名
  var label = params[2] || "測試網頁";
  var tooltip = params[3] || "開啟另一個視窗, 檢視網頁";
  var xwidth = params[4] || 550;
  var xheight = params[5] || 400;

  createTiddlyButton(place, label, tooltip,
       function(e) { config.macros.toBalaHTML.show(e,title,xfname,xwidth,xheight); },
       null, null, null);
}

config.macros.toBalaHTML.show = function(ev,xtitle,xf,xw,xh) {

  if (config.browser.isIE) {
     window.event.cancelBubble=true;
  } else {  
     ev.cancelBubble=true;   
     if (ev.stopPropagation)  
        ev.stopPropagation();
  }

  // 將視窗置中
  var winl = (screen.width-xw)/2;
  var wint = (screen.height-xh)/2;
  if (winl < 0) winl = 0;
  if (wint < 0) wint = 0;
  var settings = 'height='  + xh +  ', width=' + xw  + ',top='  + wint  + ',left='  + winl;

  if (xf != "") {

     xf=xf.replace(/\\/mg,"/");

     // alert(xf+":"+settings);
     var xwin=window.open(xf,"HTMLWIN",settings);
     xwin.window.focus();

  } else {
    // alert(store.getTiddlerText(xtitle));
    xtext=store.getTiddlerText(xtitle);

    x1=xtext.indexOf("/*{{{*/");
    x2=xtext.indexOf("/*}}}*/");
    // alert(xtext.substring(x1+8,x2));
    xtext = xtext.substring(x1+8,x2);

    var xwin=window.open('','',settings);
    xwin.document.open();
    xwin.document.write(xtext);
    xwin.document.close();
  }
}
/*
window.open() 參數
----------------------------------------------
* width:定義新視窗的寬度。
* height:定義新視窗的高度。
* resizable:能否讓用戶調整視窗大小,可能的設定值為:yes或no(或者1與0)。
* menubar:是否要顯示主功能表,可能的設定值為:yes或no。
* toolbar:是否要顯示「標準按鈕」工具列,可能的設定值為:yes或no。
* location:是否要顯示網址欄位,可能的設定值為:yes或no。
* scrollbars:能否顯示捲軸,可能的設定值為:yes或no。
* status:是否要呈現狀態列,可能的設定值為:yes或no。
* directories:是否要呈現額外的按鈕(例如:「連結」列,以及「標準按鈕」以外的其他按鈕),可能的設定值為:yes或no。
* copyhistory:是否要複製原有瀏覽器視窗的瀏覽歷程(history),可能的設定值為:yes或no。
* fullscreen:是否要以全螢幕方式開啟新視窗(適用於IE瀏覽器),可能的設定值為:yes或no。
*/
//}}}
{{item1{你可以直接載入已存在的網頁檔, 巨集如下 :}}}
{{{
<<toBalaHTML "" "ajax\html\iframe.htm" "顯示外部檔案: ajax\html\iframe.htm">>
}}}

<<toBalaHTML "" "ajax\html\iframe.htm">>

{{item1{你可以直接載入存在 tiddler 的網頁文字, 巨集如下 :}}}
{{{
<<toBalaHTML "" "" "網頁顯示 : 直接載入以下網頁文字">>
}}}

<<toBalaHTML "" "" "網頁顯示 : 直接載入以下網頁文字">>
/*{{{*/
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
</head>

<style>
body {color:red;background-color: yellow}
</style>

<body>
<h2 align=center>印出 "Hello World!"</h2>
</body>
</html>
/*}}}*/
<<toBalaHTML "" "ajax/html/e4x.htm" "網頁測試 : ajax/html/e4x.htm">><<toBalaFile "ajax\html\e4x.htm">>

///%ajax\html\e4x.htm
<html>
<script type="text/javascript;e4x=1">
      myquestion = <question>          
      <display>Is it animal, vegetable, or mineral?</display>              
      <answerOption>Animal</answerOption>
      <answerOption>Vegetable</answerOption>
      <answerOption>Mineral</answerOption>
      </question>;
      alert("The question is '" + myquestion.display + "'");             
</script>
</html>
//%/
這範例程式可在 IE, Firefox, Opera  等瀏覽器中執行

<<toBalaHTML "" "ajax\html\contentEditableFF.htm">><<toBalaFile "ajax\html\contentEditableFF.htm">>

///%ajax\html\contentEditableFF.htm
<body>
<iFrame id="jia" src="about:blank"></iFrame>  
<script>  
  // window.onload   =   function(){  
  var jia = document.getElementById("jia");  
  jia.contentWindow.document.designMode="on";  
  jia.contentWindow.document.contentEditable=true;  
  jia.contentWindow.document.open();  
  jia.contentWindow.document.write("<html><head></head><body></body></html>");  
  jia.contentWindow.document.close();  
  // }  
</script>
</body>
//%/
必須關閉瀏覽器 [阻檔 POPUP 視窗] 功能, 以下程式才能執行

<<toBalaHTML "" "ajax\html\popup.htm">><<toBalaFile "ajax\html\popup.htm">>


///%ajax\html\popup.htm
<html>
<head>
<script type="text/javascript">
function show_popup()
{
   var p=window.createPopup();
   var pbody=p.document.body;
   pbody.style.backgroundColor="lime";
   pbody.style.border="solid black 1px";
   pbody.innerHTML="This is a pop-up! Click outside to close.";
   p.show(150,150,200,50,document.body);
}
</script>
</head>

<body>
<button onclick="show_popup()">Create pop-up!</button>
</body>

</html>
//%/
/***
|''巨集名稱:''|toBalaJava|
|''版本:''|1.0 (2008-04-01)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''|toBalaRun|
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''|&lt;&lt;toBalaJava  "程式檔名"  "前置編譯參數"  "前置執行參數"  "後置執行參數" "按鈕提示資訊" "按鈕提示資訊"&gt;&gt; |
***/

//{{{
config.macros.toBalaJava = {};

config.macros.toBalaJava.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  if (readOnly) {
     return;
  }

  if (!params[0].match(".java")) {
     alert("請給檔名或副檔名錯誤");
     return;
  }

  // 程式檔名
  var xfname = params[0]; 

  // 前置編譯參數 
  var cprearg = params[1] || "";

  // 前置執行參數 
  var eprearg = params[2] || "";

  // 後置執行參數 
  var postarg = params[3] || "";

  var cargs = (cprearg=="" ? "":cprearg+" ") + xfname;
  //alert(cargs);

  var p = xfname.indexOf(".java");
  yfname=xfname.substring(0,p);
  p=yfname.lastIndexOf("\\");
  yfname=yfname.substring(p+1,yfname.length);

  var rargs = (eprearg==""?"":eprearg+" ") + yfname + (postarg==""?"":" "+postarg);
  //alert(rargs);

  // 按鈕提示資訊
  var clabel = params[4] || "翻譯程式 :" + xfname;
  var rlabel = params[5] || "執行程式 :" + yfname;

  // 翻譯程式
  createTiddlyButton(place, clabel, clabel,
       function(e) { config.macros.toBalaRun.cmd(e,"tbjavac.exe",cargs,"yes"); },
       null, null, null);

  // 執行程式
  createTiddlyButton(place, rlabel, rlabel,
       function(e) { config.macros.toBalaRun.cmd(e,"tbjava.exe",rargs,"yes"); },
       null, null, null);
}
//}}}
/***
|''巨集名稱:''|toBalaJava2|
|''版本:''|1.1 (2008-07-02)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''|toBalaRun|
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''|&lt;&lt;toBalaJava2 "程式檔名" "前置編譯參數" "前置執行參數" "後置執行參數"&gt;&gt;|
***/

//{{{
config.macros.toBalaJava2={
	
	editLabel: "程式編輯",
	editTip: "程式編輯",
	compileLabel: "編譯程式",
	compileTip: "編譯程式",
	runLabel: "執行程式",
	runTip: "執行程式",
        saveLabel: "儲存程式",
	saveTip: "儲存程式",
        cancelLabel: "取消編輯",
	cancelTip: "取消編輯",

	GUIEditButtonOnclick: function(e,xtiddler,xbox,xfname1,xx,yy) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }

            removeChildren(xbox);

            var boxtool = createTiddlyElement(xbox,"div",null,"toBalaFileToolBar",null,null);
            var boxtext = createTiddlyElement(xbox,"textarea",null,null,null,null);
            wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+xfname1+"</nowiki>@@ ",boxtool);

            createTiddlyButton(boxtool,this.saveLabel,this.saveTip,
                            function(e) { config.macros.toBalaJava2.GUISaveButtonOnclick(e,xtiddler,xbox,xfname1,boxtext,xx,yy); },
                            "toBalaFileSave",null,null);
	    createTiddlyButton(boxtool,this.cancelLabel,this.cancelTip,
                            function(e) { config.macros.toBalaJava2.GUICancelButtonOnclick(e,xtiddler,xbox,xx,yy); },
                            "toBalaFileCancel",null,null);

            // alert(xtitle+":"+xx+":"+yy);
            boxtext.setAttribute("rows",20);
            boxtext.setAttribute("cols",88);
            boxtext.value = xtiddler.text.substring(xx,yy);
        },

	GUISaveButtonOnclick: function(e,xtiddler1,xbox1,xfname2,boxtext1,xx1,yy1) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }
 
            removeChildren(xbox1);
            var xtext=boxtext1.value;
            if (config.browser.isIE) {              
               xtext=xtext.replace(/\r/g,"");   // 請看最後的註解
            }
            var toptext=xtiddler1.text.substring(0,xx1);
            var bottomtext=xtiddler1.text.substring(yy1);
            xtext = (xtext.charAt(xtext.length-1) == "\n" ? xtext : xtext+"\n");
            xtiddler1.text=toptext+xtext+bottomtext;

            story.refreshTiddler(xtiddler1.title,null,true);
            saveChanges(false);              // 參數 false, 代表不管 Dirty 與否, 均要執行存檔動作

            var baseDIR = getLocalPath(document.URL);
  
            if (config.browser.isWindows) {
                var baseDIR = baseDIR.replace(/\//g,"");
                var x = baseDIR.lastIndexOf("\\");
             } else {
                var x = baseDIR.lastIndexOf("/");
             }

            baseDIR = baseDIR.substr(0,x+1);

            var s = saveFile(baseDIR+ (config.browser.isWindows ? xfname2 : xfname2.replace(/\\/g,"\/")), 
                                          convertUnicodeToUTF8(boxtext1.value));
            if (!s) {
               alert("存檔失敗");
            }
        },

	GUICancelButtonOnclick: function(e,xtiddler1,xbox1,xx1,yy1) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }

            removeChildren(xbox1);
            story.refreshTiddler(xtiddler1.title,null,true);
        },

	handler : function(place,macroName,params,wikifier,paramString,tiddler){

              if (!params[0].match(".java")) {
                 alert("請給檔名或副檔名錯誤");
                 return;
              }

              // 程式檔名
              var xfname = params[0]; 

              // javac 編譯參數 
              var cprearg = params[1] || "";

              // java 執行參數 
              var eprearg = params[2] || "";

              // 你的程式執行參數 
              var postarg = params[3] || "";

              var cargs = (cprearg=="" ? "":cprearg+" ") + xfname;
              //alert(cargs);

              var p = xfname.indexOf(".java");
              yfname=xfname.substring(0,p);
              p=yfname.lastIndexOf("\\");
              yfname=yfname.substring(p+1,yfname.length);

              var rargs = (eprearg==""?"":eprearg+" ") + yfname + (postarg==""?"":" "+postarg);
              //alert(rargs);

	      var xtext=store.getTiddlerText(tiddler.title);

              // 取得程式段的起始位址
              var x1=xtext.indexOf("/"+"/"+"/"+"%" + xfname);

                // 自動產生程式段 (TiddlyWiki 備註)
                if (x1 == -1) { 
                   xtext=xtext+"\n\n/"+"/"+"/"+"%" + xfname + "\n" + "/"+"/"+"%"+"/";
                   tiddler.text=xtext; 
                   story.refreshTiddler(tiddler.title,null,true); // 這個 Tiddler 會重新顯示, 也就是 handler 會再被執行一次
                   //saveChanges(false);
                 }
                var x2=xtext.indexOf("/"+"/"+"%"+"/",x1);
                x1=x1+params[0].length+5;

		var box = createTiddlyElement(place,"div",tiddler.title+"-"+x1,"toBalaFile",null,null);
                var boxtool = createTiddlyElement(box,"div",null,"toBalaFileToolBar",null,null);
                wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+xfname+"</nowiki>@@ ",boxtool);

                var boxtext = createTiddlyElement(box,"div",null,null,null,null);
		wikify("{{{\n"+xtext.substring(x1,x2-1)+"\n}}}",boxtext);

                if (readOnly) {
                   return;
                }

                // 編輯程式
		createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaJava2.GUIEditButtonOnclick(e,tiddler,box,xfname,x1,x2);},
                            "toBalaFileEdit",null,null);

                // 翻譯程式
		createTiddlyButton(boxtool,this.compileLabel,this.compileTip,
                            function(e) { config.macros.toBalaRun.cmd(e,"tbjavac.exe",cargs,"yes"); },
                            "toBalaFileEdit",null,null);

                // 執行程式
                if (xtext.substring(x1,x2-1).indexOf("main") != -1) {
		       createTiddlyButton(boxtool,this.runLabel,this.runTip,
                            function(e) { config.macros.toBalaRun.cmd(e,"tbjava.exe",rargs,"yes");},
                            "toBalaFileEdit",null,null);
                }
	}		
};

/*
HTML 的 textarea 標籤, 對於換行在不同的瀏覽器有不同的處理方式

As you may know, the humble line break actually has three forms depending on which operating system is doing the breaking. On Unix machines, a single newline character ‘\n’ does the job. On Macs, a carriage return ‘\r’ is used. DOS and Windows use both: ‘\r\n’. It’s one of those relatively subtle issues that can bite you hard if you don’t know what to look out for.
*/

//}}}
{{item1{程式範例}}} 
{{{
使用 toBalaJava2 巨集, 撰寫, 編譯及執行 Java 程式, 命令格式如下 :

<<toBalaJava2 "java\hello.java" "" "">>
}}}
<<toBalaJava2 "java\hello.java" "" "">>

{{item1{程式範例 : 輸入 [編譯] 及 [執行] 參數}}}
{{{
使用 toBalaJava2 巨集, 編譯及執行 Java 程式, 命令格式如下 :
<<toBalaJava2 "java\assertion.java" "-source 1.4" "-ea">>

"-source 1.4" 是編譯參數
"-ea" 是執行參數
}}}
<<toBalaJava2 "java\assertion.java" "-source 1.4" "-ea">>

{{item1{程式範例 : 輸入程式參數}}}
{{{
使用 toBalaJava2 巨集, 編譯及執行 Java 程式, 命令格式如下 :

<<toBalaJava2 "java\args.java" "" "" "aa bb cc">>
}}}
<<toBalaJava2 "java\args.java" "" "" "aa bb cc">>


///%java\hello.java
public class hello {
  public static void main(String[] args){
     System.out.println("大家好好");
  }
}
//%/

///%java\assertion.java
class assertion {
  public static void main(String[] args){
    int i=-11;
    if (i%3==0) 
      { System.out.println("0"); }
    else if (i%3==1) 
      { System.out.println("1"); }
    else {
      assert((i%3)==2):i;
    }
  }
}
//%/

///%java\args.java
public class args {
  public static void main(String[] args) {
    for(int i=0; i < args.length ; ++i) 
      System.out.println(args[i]);
  }
} 
//%/
//{{{
if (!window.toBala) window.toBala = {};

toBala.AllTiddlers = "";
toBala.CoreTiddlers = "";

// 讀取資訊樹的架構
toBala.getMainTree = function(xstr) {
    var tbATree = new Array();
    var tbMMenu = new Array();
    var tbTemp = new Array();

    var xtext=store.getTiddlerText("MainMenu");
    tbMMenu = xtext.split("\n");

    for (var i=0,j=0; i<tbMMenu.length; ++i) {
       tbTemp = tbMMenu[i].split(" ");
       if (tbTemp[1] && tbTemp[1].indexOf(xstr) != -1) {
          tbATree[j] = tbTemp[1];
          ++j;
       }
    }
    return tbATree;
};

// 讀取資訊樹幹的所有文章
toBala.TagDigg = function(tbTag) {

   toBala.AllTiddlers = (toBala.AllTiddlers == "" ? tbTag : toBala.AllTiddlers + "," + tbTag);    

   var tbT2 = store.getTaggedTiddlers(tbTag);
   if (tbT2) {
      for (var i=0; i<tbT2.length; ++i) 
         toBala.TagDigg(tbT2[i].title);
   }
   return;
};

// 讀出 Tiddler 所有內容, 也就是 DIV 標籤內容
toBala.getTiddlerDIV = function(tbT) {
    var tiddler = store.getTiddler(tbT)
    if (!tiddler)
       return "";
   
    var usePre = config.options.chkUsePreForStorage;
    var created = tiddler.created.convertToYYYYMMDDHHMM();
    var modified = tiddler.modified.convertToYYYYMMDDHHMM();
    var vdate = version.date.convertToYYYYMMDDHHMM();
    var attributes = tiddler.modifier ? ' modifier="' + tiddler.modifier.htmlEncode() + '"' : "";
    attributes += (usePre && modified == created) ? "" : ' modified="' + modified +'"';
    attributes += (usePre && created == vdate) ? "" :' created="' + created + '"';
    var tags = tiddler.getTags();
    if (!usePre || tags)
       attributes += ' tags="' + tags.htmlEncode() + '"';

    return ('<div %0="%1"%2>%3</'+'div>').format([
	usePre ? "title" : "tiddler",
	tiddler.title.htmlEncode(),
	attributes,
	usePre ? "\n<pre>" + tiddler.text.htmlEncode() + "</pre>\n" : tiddler.text.escapeLineBreaks().htmlEncode()
	]);
}
//}}}
/***
|''巨集名稱:''|toBalaManager|
|''版本:''|1.0 (2008-09-05)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''~TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''||
***/
//{{{
config.macros.toBalaManager={
	preText: "",
	save: function(e,ytiddler,yform) {

            //for (var i=0,str="";i<yform.elements.length;++i){
            //  str=str+yform.elements[i].type+":"+yform.elements[i].tagName+":"+yform.elements[i].value;
            //}
            //alert(str);  
      
            // 設定主標題
            var xt = store.getTiddler("SiteTitle");  
            xt.text=  yform.elements[0].value;

            // 設定次標題
            var xt = store.getTiddler("SiteSubtitle");  
            xt.text=  yform.elements[1].value;

            // 設定 MainMenu
            var xt = store.getTiddler("MainMenu");  
            xt.text=  yform.elements[2].value;

            // 設定 ToolBar
            var xt = store.getTiddler("toBalaToolBar");  
            xt.text=  yform.elements[3].value;

            // 備份 SiteTitle, SiteSubtitle, ToolBar, MainMenu  
            ytiddler.text=preText; 
            saveChanges(false);   // 參數 false, 代表不管 Dirty 與否, 均要執行存檔動作
        },

	handler : function(place,macroName,params,wikifier,paramString,tiddler){

                if (!readOnly) {
		    createTiddlyButton(place,"儲存設定","儲存設定",
                          function(e) { config.macros.toBalaManager.save(e,tiddler,xform); },
                          "toBalaManagerSave",null,null);
                }

		var xform = createTiddlyElement(place,"form",tiddler.title+"-form","toBalaManager",null,null);
                // 讀取主標題
                var xlabel1 = createTiddlyElement(xform,"label",null,"",null,null);
		wikify("''主標題 (~SiteTitle) :  ''",xlabel1);
                var xtitle1 = createTiddlyElement(xform,"input",null,"xManagerMT",null,null);
                var xt = store.getTiddler("SiteTitle");   
		xtitle1.value=xt.text;
		wikify("\n\n",xform);

                // 讀取次標題
                var xlabel2 = createTiddlyElement(xform,"label",null,"",null,null);
                wikify("''次標題 (~SiteSubtitle) :  ''",xlabel2);
                var xtitle2 = createTiddlyElement(xform,"input",null,"xManagerST",null,null);
                var xt = store.getTiddler("SiteSubtitle");   
		xtitle2.value=xt.text;
		wikify("\n\n",xform);

                // 讀取 MainMenu
                var xlabel4 = createTiddlyElement(xform,"label",null,"",null,null);
                wikify("''資訊樹 (TagsTree)''",xlabel4);
		wikify("\n",xform);
                var xmm = createTiddlyElement(xform,"textarea",null,"xManagerMM",null,null);
                var xt = store.getTiddler("MainMenu");   
                xmm.value=xt.text;
		wikify("\n\n",xform);

                // 讀取 ToolBar
                var xlabel3 = createTiddlyElement(xform,"label",null,"",null,null);
                wikify("''工具列 (~ToolBar)''",xlabel3);
		wikify("\n",xform);
                var xtb = createTiddlyElement(xform,"textarea",null,"xManagerTB",null,null);
                var xt = store.getTiddler("toBalaToolBar");   
                xtb.value=xt.text;
		wikify("\n\n",xform);

                // 備份 SiteTitle, SiteSubtitle, ToolBar, MainMenu
	        var xtext=store.getTiddlerText(tiddler.title);
                var x1 = xtext.indexOf("/"+"/"+"/"+"%");
                xtext = ( x1 == -1 ? xtext : xtext.substring(0,x1) );

                preText=xtext+"\n\n/"+"/"+"/"+"%" ;
                preText=preText+"\n\n"+xtitle1.value;
                preText=preText+"\n\n"+xtitle2.value;
                preText=preText+"\n\n"+xmm.value;
                preText=preText+"\n\n"+xtb.value;
                preText=preText+"\n" + "/"+"/"+"%"+"/";

	}		
};

setStylesheet(".toBalaManager {background:#eee; font-size:12px;border:1px solid #ccc; padding:2px; margin:5px;}\n"+
".xManagerMT {width:550px;height:25px;}\n" +
".xManagerST {width:550px;height:25px;}\n" +
".xManagerTB {width:680px;height:100px;}\n" +
".xManagerMM {width:680px;height:240px;}\n" +
".toBalaManagerSave {border:1px solid #ccc;font-size:14px;padding:2px;margin-left:4px;margin-bottom:2px;}\n" ,
"toBalaManagerStyles");
//}}}
/***
|''巨集名稱:''|toBalaNotes|
|''版本:''|1.1 (2010-03-29)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''||
***/

//{{{
config.macros.toBalaNotes={
	
	editLabel: "編輯",
	editTip: "編輯",
        saveLabel: "儲存",
	saveTip: "儲存",
        cancelLabel: "取消",
	cancelTip: "取消",
        heading: "@@font-size:12px;color:#841;註解@@",
    
	GUIEditButtonOnclick: function(e,xtiddler,xbox,xx,yy) {
            removeChildren(xbox);

            var boxtool = createTiddlyElement(xbox,"div",null,"toBalaNotesToolBar",null,null);
            var boxtext = createTiddlyElement(xbox,"textarea",null,null,null,null);
	    wikify(this.heading+" : ",boxtool);

            // alert(xtitle+":"+xx+":"+yy);
            boxtext.setAttribute("rows",15);
            boxtext.setAttribute("cols",88);

            xstr=xtiddler.text.substring(xx,yy).replace(/&lt;/g, "<");
            xstr=xstr.replace(/&gt;/g, ">");
            xstr=xstr.replace(/&#123;/g, "{");
            xstr=xstr.replace(/&#125;/g, "}"); 
            boxtext.value = xstr;

            createTiddlyButton(boxtool,this.saveLabel,this.saveTip,
                            function(e) { config.macros.toBalaNotes.GUISaveButtonOnclick(e,xtiddler,xbox,boxtext,xx,yy); },
                            "toBalaNotesSave",null,null);
	    createTiddlyButton(boxtool,this.cancelLabel,this.cancelTip,
                            function(e) { config.macros.toBalaNotes.GUICancelButtonOnclick(e,xtiddler,xbox,xx,yy); },
                            "toBalaNotesCancel",null,null);
        },

	GUISaveButtonOnclick: function(e,xtiddler1,xbox1,boxtext1,xx1,yy1) {
            removeChildren(xbox1);
            toptext=xtiddler1.text.substring(0,xx1);
            bottomtext=xtiddler1.text.substring(yy1);

            xstr=boxtext1.value.replace(/\</g, "&lt;");
            xstr=xstr.replace(/>/g, "&gt;");
            xstr=xstr.replace(/{/g, "&#123;");
            xstr=xstr.replace(/}/g, "&#125;");
            xstr=xstr.replace(/\/\/%\//g, "");
            xstr=xstr.replace(/\/\/\/%/g, "");
            xtiddler1.text=toptext+xstr+bottomtext;

            yy1=xtiddler1.text.indexOf("/"+"/"+"%"+"/",xx1);

            var boxtool = createTiddlyElement(xbox1,"div",null,"toBalaNotesToolBar",null,null);
	    wikify(this.heading+" : ",boxtool);

	    createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaNotes.GUIEditButtonOnclick(e,xtiddler1,xbox1,xx1,yy1);},
                            "toBalaNotesEdit",null,null);

             var boxarea = createTiddlyElement(xbox1,"div",null,null,null,null); 
             boxarea.innerHTML="<pre id='toBalaNotesText'>"+xstr+"</pre>";
	     // wikify("<nowiki>"+xtiddler1.text.substring(xx1,yy1)+"</nowiki>",boxarea);
             saveChanges(false);   // 參數 false, 代表不管 Dirty 與否, 均要執行存檔動作
             clearMessage();
        },

	GUICancelButtonOnclick: function(e,xtiddler1,xbox1,xx1,yy1) {
            removeChildren(xbox1);

            var boxtool = createTiddlyElement(xbox1,"div",null,"toBalaNotesToolBar",null,null);
	    wikify(this.heading+" : ",boxtool);

	    createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaNotes.GUIEditButtonOnclick(e,xtiddler1,xbox1,xx1,yy1);},
                            "toBalaNotesEdit",null,null);

             var boxarea = createTiddlyElement(xbox1,"div",null,null,null,null);
             boxarea.innerHTML="<pre id='toBalaNotesText'>"+xtiddler1.text.substring(xx1,yy1)+"</pre>";
	     //wikify("<nowiki>"+xtiddler1.text.substring(xx1,yy1)+"</nowiki>",boxarea);
        },

	handler : function(place,macroName,params,wikifier,paramString,tiddler){

		var xtext=store.getTiddlerText(tiddler.title);
                var x1=xtext.indexOf("/"+"/"+"/"+"%" + params[0]);

                // 自動產生 TiddlyWiki 備註
                if (x1 == -1) { 
                   xtext=xtext+"\n\n/"+"/"+"/"+"%" + params[0] + "\n" + "/"+"/"+"%"+"/";
                   tiddler.text=xtext; 
                   story.refreshTiddler(tiddler.title,null,true);
                   saveChanges(false);     // 參數 false, 代表不管 Dirty 與否, 均要執行存檔動作
                   clearMessage();
                   return;
                 }
                var x2=xtext.indexOf("/"+"/"+"%"+"/",x1);
                x1=x1+params[0].length+5;

		var box = createTiddlyElement(place,"div",tiddler.title+"-"+x1,"toBalaNotes",null,null);
                var boxtool = createTiddlyElement(box,"div",null,"toBalaNotesToolBar",null,null);
		wikify(this.heading+" : ",boxtool);

                var boxtext = createTiddlyElement(box,"div",null,null,null,null);
                boxtext.innerHTML="<pre id='toBalaNotesText'>"+xtext.substring(x1,x2)+"</pre>";
		// wikify("<nowiki>"+xtext.substring(x1,x2)+"</nowiki>",boxtext);

                if (readOnly) {
                   return;
                }

		createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaNotes.GUIEditButtonOnclick(e,tiddler,box,x1,x2);},
                            "toBalaNotesEdit",null,null);
	}		
};

setStylesheet(".toBalaNotes {background:#eee; border:1px solid #ccc; padding:2px; margin:5px;}\n"+
".toBalaNotesEdit {border:1px solid #ccc;padding:2px;margin-top:2px;margin-bottom:2px;}\n" +
".toBalaNotesCancel {border:1px solid #ccc;padding:2px;margin-top:2px;margin-right:2px;margin-bottom:2px;}\n" +
".toBalaNotesToolBar {border-bottom: 2px dotted #556b2f;padding:1px 0px 5px 0px;margin:1px;}\n" +
".toBalaNotesSave {border:1px solid #ccc;padding:2px;margin-top:2px;margin-right:2px;margin-bottom:2px;}\n"+
"#toBalaNotesText {background-color:#eee;border:none;margin:1px;padding:0px}\n",
"toBalaNotesStyles");
//}}}
在文章中使用 toBalaNotes 巨集, 可在文章中加入備註, 請看以下使用說明

{{item1{使用格式}}}
{{{
<<toBalaNotes "test">>

"test" 代表備註識別字串

[註] 一篇文章中可以存在多個備註
}}}

<<toBalaNotes "test">>

///%test
//%/
/***
|''巨集名稱:''|toBalaRun|
|''版本:''|1.0 (2008-04-01)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''| |
***/

//{{{
config.macros.toBalaRun = {};
config.macros.toBalaRun.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  if (readOnly) {
     return;
  }

  if (!params[0]) {
     alert("請給檔名");
     return;
  }
  var fname = params[0];                //  執行檔名
  var varg = params[1] || "";             //  執行參數
  var label = params[2] || "執行 : "+fname + " " + varg;
  var tooltip = params[3] || "執行檔名 : "+fname + " " + varg;
  var result = params[4] || "yes";

  window.status="";
  createTiddlyButton(place, label, tooltip,
       function(e) { config.macros.toBalaRun.cmd(e,fname,varg,result); },
       null, null, null);
}

config.macros.toBalaRun.cmd = function(ev,xfname,xarg,xresult) {

  if (!xfname.match(".bat")) {
      //var xwin = toBala.showMsg("<h1>執行中, 請稍後</h1>",250,50);
      window.status = xfname + " " + xarg + " 執行中, 請稍後";
  }

  if (config.browser.isIE) {
     window.event.cancelBubble=true;
  } else {  
     ev.cancelBubble = true;   
     if (ev.stopPropagation)  
        ev.stopPropagation();
  }

  var baseDIR = getLocalPath(document.URL);
  //alert(baseDIR);

   if (config.browser.isWindows) {
      var baseDIR = baseDIR.replace(/\//g,"");
      var x = baseDIR.lastIndexOf("\\");
      xfname = "\\" + xfname.replace(/\//g,"\\");
      xarg = xarg.replace(/\//g,"\\");
   } else {
      var x = baseDIR.lastIndexOf("/");
      xfname = "/" + xfname.replace(/\\/g,"/");
      xarg = xarg.replace(/\\/g,"/");
   }

   baseDIR = baseDIR.substr(0,x);
   //alert(baseDIR);

   if (config.browser.isIE) {
	var theShell = new ActiveXObject("WScript.Shell");
	if (theShell) {
            var runstr = baseDIR + xfname + " " + xarg;
            // alert(runstr);
	    try {
	        theShell.run(runstr,1, (xresult == "yes" ? true:false));
	    } catch (e) {
                try {          //  執行系統命令
                    var runstr = xfname.substring(1)+ " " + xarg;
                    theShell.run(runstr,1, (xresult == "yes" ? true:false));
                } catch(e) {
                   if (!xfname.match(".bat")) 
                      window.status="";
		   displayMessage("執行失敗 :" + runstr);
		   return;
                }
	    }
	} 
   } else if (config.browser.isGecko) { 
	netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
        var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);

        try {
           var runstr = baseDIR +xfname; 
           // alert(runstr);
           file.initWithPath(runstr);
        }catch (e) {
           if (!xfname.match(".bat")) 
              window.status="";
           displayMessage("執行字串格式錯誤 : " + runstr);
           return;
        }

	try {
	   var process = Components.classes['@mozilla.org/process/util;1'].createInstance(Components.interfaces.nsIProcess);
           var Aargs = xarg.split(" ");
           // alert(Aargs);
           process.init(file);
           process.run((xresult == "yes" ? true:false), Aargs, Aargs.length);
	} catch (e) {
            try {    //  執行系統命令
                runstr=xfname.substring(1);
                file.initWithPath(runstr);
                process.init(file);
                process.run((xresult == "yes" ? true:false), Aargs, Aargs.length);
            } catch (e) {
                if (!xfname.match(".bat")) 
                    window.status="";
	        displayMessage("執行失敗 : " + runstr);
                return;
            }
	}
   }
   // 顯示執行結果
   if ( !xfname.match(".bat") && !xfname.match(".sh") && xresult == "yes") {
      window.status="";
      xf = baseDIR+xfname+".htm"
      // alert(xf);
      var xh = 400;
      var xw = 780;
      var winl = (screen.width-xw)/2;
      var wint = (screen.height-xh)/2;
      if (winl < 0) winl = 0;
      if (wint < 0) wint = 0;
      var settings = 'height='  + xh +  ', width=' + xw  + ',top='  + wint  + ',left='  + winl + ',scrollbars=yes';
      var ywin=window.open("file:///"+xf,"HTMLWIN",settings);
   }
}
//}}}
在文章中使用 toBalaRun 巨集, 可執行系統中的 ''命令'', ''批次檔'', 請看以下使用說明

{{item1{使用格式}}}

__在 Windows 系統中, 啟動 tbsys.bat  批次檔__
{{{
<<toBalaRun "tbsys.bat"  ""  "System Info (batch)">>
}}}
<<toBalaRun "tbsys.bat" "" "System Info (batch)">>


__在 Windows 系統中, 因執行 exe 檔, 執行後會自動開啟一個 [執行結果視窗]__
{{{
<<toBalaRun  "tbsys.exe"  ""  "System Info (exe)">>
}}}
<<toBalaRun "tbsys.exe" "" "System Info (exe)">>

__在 Mac OS X 系統中, 啟動 ~TextEdit 應用程式, 因最後一個參數是 "no", 所以不會開啟一個 [執行結果視窗] __
{{{
<<toBalaRun "/usr/bin/open"  "-a /Applications/TextEdit.app"  ""  ""  "no">>
}}}
<<toBalaRun "/usr/bin/open" "-a /Applications/TextEdit.app" "" "" "no">>


{{item1{tbsys.bat 批次檔內容}}}
{{{
@echo off

REM 取得這個 Batch File 的目錄
set toBalaPath=%~p0

REM 取得這個 Batch File 的磁碟代號
set toBalaDrv=%~d0

REM 轉換磁碟及目錄
call %toBalaDrv%
cd %toBalaPath%

REM 設定環境變數
REM -----------------
set JAVA_HOME=%cd%\jdk1.6.0_05
set CLASSPATH=.;%cd%\jaxp;%cd%\java;%cd%\scjp
set CLASSPATH=%cd%\apache\xalan-j_2_7_1\xalan.jar;%CLASSPATH%
set CLASSPATH=%cd%\apache\xerces-2_9_1\xercesImpl.jar;%CLASSPATH%
set PATH=.;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;%cd%\cmdtools;%PATH%


REM 執行 java 命令
REM ------------------
if "%~x0" == ".bat" goto n1
echo ^<head^> >%0.htm
echo ^<meta http-equiv="Content-Type" content="text/html; charset=big5"^> >>%0.htm
echo ^</head^> >>%0.htm
echo ^<body^> >>%0.htm
echo 執行檔案 : %1 >>%0.htm
echo ^<hr^> >>%0.htm 
echo ^<pre style='font-size:12px'^> >>%0.htm
goto n2
:n1
echo 執行中, 請稍待 (檔案 : %1) 
echo. >%0.htm
:n2

gettype >> %0.htm 2>&1
echo.
ipconfig /all >> %0.htm 2>&1

REM 處理執行訊息
REM -------------------
if "%~x0" == ".bat" goto s1
echo ^</pre^> >>%0.htm
echo ^</body^> >>%0.htm
rem convertZ\convertz /i:big5 /o:utf8 %0.msg %0.htm
exit
:s1
type %0.htm
echo.
echo 執行完成
echo.
pause
}}}

{{item1{Quick Batch File Compiler - 將 Batch 檔轉換成 exe 檔}}}
Quick Batch File Compiler convert your batch files into actual program (.EXE format) in one click. This program may be run on Windows 2000/2003/XP/Vista without any limitations. An .EXE file is much harder to casually reverse-engineer, so this could be a way to conceal a particular batch file's operations from an end user. Content of your batch file will be encrypted and protected from changes.

Quick Batch File Compiler also lets you set various resources in the .EXE file, such as its description, the company name, version information and even the application icon. In additional, you may include any files to compiled exe file and use it during execution. 

網址 : http://www.abyssmedia.com/quickbfc/index.shtml
<<toBalaFile "xml\dtd01.xml">><<toBalaRun "java\jaxp\JAXPDTD.bat" "xml\dtd01.xml" "檢核">>

----

<<toBalaFile "xml\dtd02.xml">><<toBalaRun "java\jaxp\JAXPDTD.bat" "xml\dtd02.xml" "檢核">>


///%xml\dtd01.xml
<?xml version="1.0" encoding="big5"?>
<!DOCTYPE PersonData [
  <!ELEMENT PersonData (name,spouse)>
  <!ELEMENT name (#PCDATA)>
  <!ELEMENT spouse (#PCDATA)>
]>
<PersonData>
    <spouse>Teley</spouse>
    <name>Ryan</name>
</PersonData>
//%/

///%xml\dtd02.xml
<?xml version="1.0"?>
<!DOCTYPE user [
  <!ELEMENT user (name+,e-mail*,title?)>
  <!ELEMENT name (#PCDATA)>
  <!ELEMENT e-mail (#PCDATA)>
  <!ELEMENT title (#PCDATA)>
]>
<user>
  <name>Austin Sours</name>
  <e-mail>xchen@cmt.com.tw</e-mail>
  <e-mail>aaa@x,y,z</e-mail>
</user>
//%/
<<toBalaFile "xml\well01.xml">><<toBalaRun "java\jaxp\JAXPWell.bat" "xml\well01.xml" "檢核">>

----

<<toBalaFile "xml\well02.xml">><<toBalaRun "java\jaxp\JAXPWell.bat" "xml\well02.xml" "檢核">>


///%xml\well01.xml
<root>
  <marble color="red"/>
  <marble color='red'/>
</root>
//%/

///%xml\well02.xml
<first_tag>
  <second_tag>
     <third_tag>Contents of third tag
  </second_tag>
</First_tag>
//%/
<<toBalaFile "xml\stype.xsd">>


<<toBalaFile "xml\stype.xml">><<toBalaRun "java\jaxp\JAXPSchema.bat" "xml\stype.xml xml\stype.xsd" "檢核">>


///%xml\stype.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
                  targetNamespace="http://xsdtesting">
    <xs:element name="author" type="xs:date"/>
</xs:schema>
//%/

///%xml\stype.xml
<?xml version="1.0"?>
<x:author xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
          xmlns:x="http://xsdtesting"
          xsi:schemaLocation="http://xsdtesting stype.xsd">
123.5
</x:author>
//%/
<<toBalaFile "xml\deftemp.xml">>
DOM Tree
----------------
{{{
       .
       |
       |--- <?xml-stylesheet  type="text/xsl"  .... ?>   
       |--- <root>
                |
                |--- <text>
                |
                |
                |--- <text>
                |
                |
                |--- <!-- abcd --> 

}}}


<<toBalaFile "xml\deftemp.xsl">><<toBalaRun "java\jaxp\JAXPXSLT.bat" "xml\deftemp.xml xml\deftemp.xsl" "轉換">>


///%xml\deftemp.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="deftemp.xsl"?>
<root>
  <text>
    Roses are <color>red</color>, violets are <color>blue</color>.
  </text>
  <text>
    My <color>green</color> and <color id="xxx">yellow</color> 
    sweater is just the right hue.
    <?name type="bebo"?>
  </text>
  <!-- abcd -->
</root>
//%/

///%xml\deftemp.xsl
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<!-- <xsl:template match="*|/">
</xsl:template>  -->

<!-- <xsl:template match="processing-instruction()">
  PI : <xsl:value-of select="."/>
</xsl:template> -->

<!-- <xsl:template match="root"/> -->

</xsl:stylesheet>
//%/
{{item1{ZoomIt v1.8}}}
By Mark Russinovich
Published: March 10, 2008
網址 : http://technet.microsoft.com/zh-tw/sysinternals/bb897434(en-us).aspx

__''Introduction''__
~ZoomIt is screen zoom and annotation tool for technical presentations that include application demonstrations. ~ZoomIt runs unobtrusively in the tray and activates with customizable hotkeys to zoom in on an area of the screen, move around while zoomed, and draw on the zoomed image. I wrote ~ZoomIt to fit my specific needs and use it in all my presentations.

~ZoomIt works on all versions of Windows and you can use pen input for ~ZoomIt drawing on tablet ~PCs.

__''Using ~ZoomIt''__
The first time you run ~ZoomIt it presents a configuration dialog that describes ~ZoomIt's behavior, let's you specify alternate hotkeys for zooming and for entering drawing mode without zooming, and customize the drawing pen color and size. I use the draw-without-zoom option to annotate the screen at its native resolution, for example. ~ZoomIt also includes a break timer feature that remains active even when you tab away from the timer window and allows you to return to the timer window by clicking on the ~ZoomIt tray icon.

點選 <<toBalaRun "tbzoomit.bat" "" "ZoomIt v1.8" "" "no">> 啟動 Zoomit

{{item1{tbzoomit.bat 程式碼}}}
{{{
@echo off

REM 取得這個 Batch File 的目錄
set toBalaPath=%~p0

REM 取得這個 Batch File 的磁碟代號
set toBalaDrv=%~d0

REM 轉換磁碟及目錄
call %toBalaDrv%
cd %toBalaPath%

REM 設定環境變數
REM -----------------
set PATH=.;%cd%\tools;%cd%\tools\cmdtools;%PATH%
start /B zoomit.exe
exit

}}}
網址 : http://freemind.sourceforge.net/wiki/index.php/Main_Page

~FreeMind is a premier free mind-mapping (http://en.wikipedia.org/wiki/Mind_map) software written in Java. The recent development has hopefully turned it into high productivity tool. We are proud that the operation and navigation of ~FreeMind is faster than that of MindManager because of one-click "fold / unfold" and "follow link" operations.

So you want to write a completely new metaphysics? Why don't you use ~FreeMind? You have a tool at hand that remarkably resembles the tray slips of Robert Pirsig, described in his sequel to Zen and the Art of Motorcycle Maintenance called Lila. Do you want to refactor your essays in a similar way you would refactor software? Or do you want to keep personal knowledge base, which is easy to manage? Why don't you try ~FreeMind? Do you want to prioritize, know where you are, where you've been and where you are heading, as Stephen Covey would advise you? Have you tried FreeMind to keep track of all the things that are needed for that? 

Mac OS X 系統請點選以下按鈕

<<toBalaRun "java/freemind/freemind.sh"  ""  "啟動心智圖編輯器">>


Windows 系統請點選以下按鈕

<<toBalaRun "tbfreemind.bat"  ""  "啟動心智圖編輯器">>
/***
|''巨集名稱:''|toBalaSWF2|
|''版本:''|1.1 (2008-09-30)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''| |
***/
//{{{
config.macros.toBalaSWF2 = {};

config.macros.toBalaSWF2.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  var xname = params[0] || tiddler.title;
  var xwidth = params[1] || 600;
  var xheight = params[2] || 450;
  var label = params[3] || "撥放 : " + xname;

  createTiddlyButton(place, label, label,
       function(e) { config.macros.toBalaSWF2.show(e, xname, xwidth, xheight); },
       null, null, null);
}

config.macros.toBalaSWF2.show = function(ev,fname,xw,xh) {

  if (config.browser.isIE) {
     window.event.cancelBubble=true;
  } else {  
     ev.cancelBubble = true;   
     if (ev.stopPropagation)  
        ev.stopPropagation();
  }

  if (config.browser.isIE)
     var URLtext = document.URL.replace(/\\/g,"\/");
  else 
     var URLtext = document.URL;
  //alert(URLtext);

  var x = URLtext.lastIndexOf("/");
  var baseDIR = URLtext.substr(0,x);
  //alert(jsDIR);

  // 將視窗置中
  var winl = (screen.width-xw)/2;
  var wint = (screen.height-xh)/2;
  if (winl < 0) winl = 0;
  if (wint < 0) wint = 0;
  var settings = 'scrollbars=yes, resizable=yes, height='  + xh +  ', width=' + xw  + ',top='  + wint  + ',left='  + winl;
  var gen=window.open('',"_blank",settings);

  gen.document.open();
  gen.document.write("<html>");
  gen.document.write("<head>");
  gen.document.write("  <title>toBalaSWF2 : " + fname + "</title>");
  gen.document.write("  <script type='text/javascript' src='" + baseDIR + "/jslib/swfobject21/swfobject.js'></script>");
  gen.document.write("  <script type='text/javascript'>");
  gen.document.write("     swfobject.embedSWF('" + baseDIR + '/' + fname + "', 'mySWF21', '" + xw + "','" + xh + "', '9.0.0');");
  gen.document.write("  </script>");
  gen.document.write("</head>");
  gen.document.write("<body style='margin:0;padding:0'>");
  gen.document.write("  <div style='margin:0;padding:0;" +"width:" + (xw+2) +";height:" + (xh+2) +"' id='mySWF21'>");
  gen.document.write("    <p>無法撥放</p>");
  gen.document.write("  </div>");
  gen.document.write("</body>");
  gen.document.write("</html>");

  gen.document.close();
}
//}}}
/***
|''巨集名稱:''|toBalaTest|
|''版本:''|1.0 (2010-04-27)|
|''原始檔:''||
|''作者:''|Sung-Lin CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''||
***/

//{{{
config.macros.toBalaTest = {
  handler :  function(place,macroName,params,wikifier,paramString,tiddler) {

     var label = params[0] || "測試開始";
     var tooltip = params[1] || "開啟一個測試視窗";

     if (!params[2]) {
        alert("請給題庫名稱");
        return;
     } 
    
     if (!params[3]) {
        alert("請給題數");
        return;
     } 

     var xSubject = params[2];
     var xNumber = params[3];
     var xwidth = params[4] || 550;
     var xheight = params[5] || 400;
     var xcw = params[6] || "100%";
     var xch = params[7] || "100%";

     // 取出考題
     var xtext=store.getTiddlerText(tiddler.title);
     var x1=xtext.indexOf("/"+"/"+"/"+"%" + xSubject);
     x1=x1+ xSubject.length + 5;
     var x2=xtext.indexOf("/"+"/"+"%"+"/",x1);
     var xContent = xtext.substring(x1,x2);

     // 轉換成考題陣列
     var myTest = eval(xContent);

     // 打亂考題
     var tn=myTest.length;
     for(i=1;i<=500;i++) {
        j = Math.floor(Math.random() * tn);
        k = Math.floor(Math.random() * tn);
       
        var op;
        for (op in myTest[j])
           myTest[tn-1][op]=myTest[j][op];

        for (op in myTest[k])
           myTest[j][op]=myTest[k][op];

        for (op in myTest[tn-1])
           myTest[k][op]=myTest[tn-1][op];
     }

     // 確認題數
     xNumber = (xNumber<=myTest.length)? xNumber : myTest.length;

     // 將考題轉成網頁
     var xText="",i;
     for(i=1;i<=xNumber;++i) {
        xText=xText + "<div id='"+xSubject+i+"' style='position:absolute;left:10px;top:10px;visibility:hidden;'>";
        xText=xText + "第 " + i + "/" + xNumber + " 題" + "&nbsp;&nbsp;<input type='text' id='xTest_Input"+ i + "'/>";
        xText=xText + "&nbsp;<button onclick='xUp();'>上一題</button>&nbsp;<button onclick='xDown();'>下一題</button>";
        xText=xText + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<button onclick='xScore();'>結束</button>&nbsp;";
        xText=xText + "<span style='visibility:hidden;color:red;' id='xTest_Answer"+i+"'>"+myTest[i][1]+"</span>";
        xText=xText + "<br/><br/><img style='border:1px solid black' src='"+myTest[i][0]+"' width='"+xcw+"' height='"+xch+"'/>";
        xText=xText + "</div>";
     }

     // 操作按鈕程式製作
     xText = xText + "<script>";
     xText = xText + "var xNumber=1, xNumberMax="+ xNumber +";var xSub='"+xSubject+"';";
     xText = xText + "document.getElementById(xSub+xNumber).style.visibility=''; ";
     xText = xText + "function xUp() { if (xNumber>1) {xNumber--;";
     xText = xText + "        document.getElementById(xSub+xNumber).style.visibility=''; ";
     xText = xText + "        document.getElementById(xSub+(xNumber+1)).style.visibility='hidden';} }";
     xText = xText + "function xDown() { if (xNumber<xNumberMax) {xNumber++;";
     xText = xText + "         document.getElementById(xSub+xNumber).style.visibility=''; ";
     xText = xText + "         document.getElementById(xSub+(xNumber-1)).style.visibility='hidden';} }";
     xText = xText + "function xScore() { var xc=0; var xA='';";
     xText = xText + "    for (i=1; i<=xNumberMax; ++i) {";
     xText = xText + "         xA=document.getElementById('xTest_Answer'+i).innerHTML.toLowerCase();";
     xText = xText + "         if (xA==document.getElementById('xTest_Input'+i).value.toLowerCase()) {"; 
     xText = xText + "            xc++;document.getElementById('xTest_Answer'+i).style.visibility='hidden' }";
     xText = xText + "         else { document.getElementById('xTest_Answer'+i).style.visibility=''; }";
     xText = xText + "    }";
     xText = xText + "    alert('共 ' + xNumberMax +' 題 : 答對 '+ xc +' 題'); }";
     xText = xText + "</script>";

     createTiddlyButton(place, label, tooltip,
         function(e) { config.macros.toBalaTest.run(e,xText,xwidth,xheight); },
         null, null, null);
  },

  run : function(ev,xct,xw,xh) {

     if (config.browser.isIE) {
        window.event.cancelBubble=true;
     } else {  
        ev.cancelBubble=true;   
        if (ev.stopPropagation)  
           ev.stopPropagation();
     }

     // 將視窗置中
     var winl = (screen.width-xw)/2;
     var wint = (screen.height-xh)/6;
     if (winl < 0) winl = 0;
     if (wint < 0) wint = 0;
     var settings = 'height='  + xh +  ', width=' + xw  + ',top='  + wint  + ',left='  + winl + ',scrollbars=yes';

     // 顯示考題網頁
     var xTest="<html><body style='color:black;font-size=36px;font-weight:bold'>" + xct + "</body></html>";

     // 開啟測試視窗
     var xwin=window.open('','',settings);
     xwin.document.open();
     xwin.document.write(xTest);
     xwin.document.close();
  } 
};
/*
利用 eval() 來將 JSON 字串轉成物件,不過字串的前後記得要加上刮號 (),這是用來告知 Javascript Interpreter 這是個物件描述,不是要執行的 statement。

但是呼叫 eval() 是危險的,因為他會執行任何字串中的 Javascript 程式碼,容易有 XSS 攻擊的危險,所以一般都建議引用官網上所提供的 parser - http://www.json.org/json.js 。
*/
//}}}
 [[首頁]] | [[土芭樂 3.0 - 數位新思路|http://tbala.net/]]  | [[TiddlyWiki 練功坊|http://tiddlywiki.tbala.net/]] | [[匯入文章]]  | [[匯出文章]]  |  &nbsp;&nbsp;<<toBalaRun "Java-CMD.bat" "" "命令提示視窗">>&nbsp;&nbsp;<<newTiddler label:"新增文章">>&nbsp;&nbsp;<<closeAll>>&nbsp;&nbsp;<<saveChanges>> &nbsp;&nbsp;IT 無涯,關機是岸 
/***
|''巨集名稱:''|toBalaWrite|
|''版本:''|1.0 (2008-09-01)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''| |
***/

//{{{
config.macros.toBalaWrite = {};
config.macros.toBalaWrite.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	var title = params[0];
	if (title == tiddler.title) {
            title = "Error: Can't use the same tiddler from which the macro is called (infinite recursion)!";
            alert(title);
            return;
	}
	var tiddler = store.getTiddler(title);
        var contents = tiddler.text;
	wikify(contents, place);
}
//}}}
Steps To Getting VMware Tools installed on Ubuntu Hardy under VMware Fusion:

Use the “Install VMware Tools” option in VMWare Fusion, and drag the .tar file (not the RPM!) to the Ubuntu desktop.

Open a Terminal (Applications menu -> Accessories -> Terminal). We’ll do all the work from the Terminal. First, we need to install some dependencies:

    sudo apt-get install build-essential libgtk2.0-dev
    sudo apt-get install libproc-dev libdumbnet-dev xorg-dev
    cd Desktop/

    wget http://mesh.dl.sourceforge.net/sourceforge/open-vm-tools/open-vm-tools-2008.04.14-87182.tar.gz

Next, we need to unpack the tar files we have at hand:

    tar xzvf VMware*.gz
    tar xzvf open-vm-tools*.gz

Next, we’ll build the open-vm-tools:

    cd open-vm-tools-2008.04.14-87182/
    ./configure && make
    cd modules/linux/

In the modules/linux folder we have the vmblock, vmhgfs, vmmemctl, vmsync and vmxnet modules that we need to tar up and place into the official VMware tools tarball:

    for i in *; do mv ${i} ${i}-only; tar -cf ${i}.tar ${i}-only; done
    cd ../../..

    mv -f open-vm-tools-2008.04.14-87182/modules/linux/*.tar vmware-tools-distrib/lib/modules/source/

Now we can run the regular VMware tools installer:

    cd vmware-tools-distrib/
    sudo ./vmware-install.pl

Once this is done, the best tactic is to restart Ubuntu entirely. Once you boot back up, things should seem a bit smoother. The resolution of the VM will stick to the size of the VM, etc, and you can now drag files directly into Ubuntu Hardy from your Mac desktop!

/***
|''Name:''|DropDownMenuPlugin|
|''Description:''|Create dropdown menus from unordered lists|
|''Author:''|Saq Imtiaz ( lewcid@gmail.com )|
|''Source:''|http://tw.lewcid.org/#DropDownMenuPlugin|
|''Code Repository:''|http://tw.lewcid.org/svn/plugins|
|''Version:''|2.1|
|''Date:''|11/04/2007|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.2.5|

!!Usage:
* create a two-level unordered list using wiki syntax, and place {{{<<dropMenu>>}}} on the line after it.
* to create a vertical menu use {{{<<dropMenu vertical>>}}} instead.
* to assign custom classes to the list, just pass them as parameters to the macro {{{<<dropMenu className1 className2 className3>>}}}

!!Features:
*Supports just a single level of drop-downs, as anything more usually provides a poor experience for the user.
* Very light weight, about 1.5kb of JavaScript and 4kb of CSS.
* Comes with two built in css 'themes', the default horizontal and vertical. 

!!Customizing:
* to customize the appearance of the menu's, you can either add a custom class as described above or, you can edit the CSS via the StyleSheetDropDownMenu shadow tiddler.


***/
// /%
//!BEGIN-PLUGIN-CODE
config.macros.dropMenu={

	dropdownchar: "\u25bc",

	handler : function(place,macroName,params,wikifier,paramString,tiddler){
		list = findRelated(place.lastChild,"UL","tagName","previousSibling");
		if (!list)
			return;
		addClass(list,"suckerfish");
		if (params.length){
			addClass(list,paramString);
		}
		this.fixLinks(list);
	},
	
	fixLinks : function(el){
		var els = el.getElementsByTagName("li");
		for(var i = 0; i < els.length; i++) {
			if(els[i].getElementsByTagName("ul").length>0){
				var link = findRelated(els[i].firstChild,"A","tagName","nextSibling");
				if(!link){
					var ih = els[i].firstChild.data;
					els[i].removeChild(els[i].firstChild);
					var d = createTiddlyElement(null,"a",null,null,ih+this.dropdownchar,{href:"javascript:;"});
					els[i].insertBefore(d,els[i].firstChild);
				}
				else{
					link.firstChild.data = link.firstChild.data + this.dropdownchar;
					removeClass(link,"tiddlyLinkNonExisting");
				}
			}
			els[i].onmouseover = function() {
				addClass(this, "sfhover");
			};
			els[i].onmouseout = function() {
				removeClass(this, "sfhover");
			};
		}
	}	
};

config.shadowTiddlers["StyleSheetDropDownMenuPlugin"] = 
	 "/*{{{*/\n"+
	 "/***** LAYOUT STYLES -  DO NOT EDIT! *****/\n"+
	 "ul.suckerfish, ul.suckerfish ul {\n"+
	 "	margin: 0;\n"+
	 "	padding: 0;\n"+
	 "	list-style: none;\n"+
	 "	line-height:1.4em;\n"+
	 "}\n\n"+
	 "ul.suckerfish  li {\n"+
	 "	display: inline-block; \n"+
	 "	display: block;\n"+
	 "	float: left; \n"+
	 "}\n\n"+
	 "ul.suckerfish li ul {\n"+
	 "	position: absolute;\n"+
	 "	left: -999em;\n"+
	 "}\n\n"+
	 "ul.suckerfish li:hover ul, ul.suckerfish li.sfhover ul {\n"+
	 "	left: auto;\n"+
	 "}\n\n"+
	 "ul.suckerfish ul li {\n"+
	 "	float: none;\n"+
	 "	border-right: 0;\n"+
	 "	border-left:0;\n"+
	 "}\n\n"+
	 "ul.suckerfish a, ul.suckerfish a:hover {\n"+
	 "	display: block;\n"+
	 "}\n\n"+
	 "ul.suckerfish li a.tiddlyLink, ul.suckerfish li a, #mainMenu ul.suckerfish li a {font-weight:bold;}\n"+
	 "/**** END LAYOUT STYLES *****/\n"+
	 "\n\n"+
	 "/**** COLORS AND APPEARANCE - DEFAULT *****/\n"+
	 "ul.suckerfish li a {\n"+
	 "	padding: 0.5em 1.5em;\n"+
	 "	color: #FFF;\n"+
	 "	background: #0066aa;\n"+
	 "	border-bottom: 0;\n"+
	 "	font-weight:bold;\n"+
	 "}\n\n"+
	 "ul.suckerfish li:hover a, ul.suckerfish li.sfhover a{\n"+
	 "	background: #00558F;\n"+
	 "}\n\n"+
	 "ul.suckerfish li:hover ul a, ul.suckerfish li.sfhover ul a{\n"+
	 "	color: #000;\n"+
	 "	background: #eff3fa;\n"+
	 "	border-top:1px solid #FFF;\n"+
	 "}\n\n"+
	 "ul.suckerfish ul li a:hover {\n"+
	 "	background: #e0e8f5;\n"+
	 "}\n\n"+
	 "ul.suckerfish li a{\n"+
	 "	width:9em;\n"+
	 "}\n\n"+
	 "ul.suckerfish ul li a, ul.suckerfish ul li a:hover{\n"+
	 "	display:inline-block;\n"+
	 "	width:9em;\n"+
	 "}\n\n"+
	 "ul.suckerfish li {\n"+
	 "	border-left: 1px solid #00558F;\n"+
	 "}\n"+
	 "/***** END COLORS AND APPEARANCE - DEFAULT *****/\n"+
	 "\n\n"+
	 "/***** LAYOUT AND APPEARANCE: VERTICAL *****/\n"+
	 "ul.suckerfish.vertical li{\n"+
	 "	width:10em;\n"+
	 "	border-left: 0px solid #00558f;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical ul li, ul.suckerfish.vertical li a, ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a {\n"+
	 "	border-left: 0.8em solid #00558f;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical li a, ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a,  ul.suckerfish.vertical li.sfhover a:hover{\n"+
	 "	width:8em;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical {\n"+
	 "	width:10em; text-align:left;\n"+
	 "	float:left;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical li a {\n"+
	 "	padding: 0.5em 1em 0.5em 1em;\n"+
	 "	border-top:1px solid  #fff;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical, ul.suckerfish.vertical ul {\n"+
	 "	line-height:1.4em;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical li:hover ul, ul.suckerfish.vertical li.sfhover ul { \n"+
	 "	margin: -2.4em 0 0 10.9em;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical li:hover ul li a, ul.suckerfish.vertical li.sfhover ul li a {\n"+
	 "	border: 0px solid #FFF;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a{\n"+
	 "	padding-right:1.1em;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical li:hover ul li, ul.suckerfish.vertical li.sfhover ul li {\n"+
	 "	border-bottom:1px solid  #fff;\n"+
	 "}\n\n"+
	 "/***** END LAYOUT AND APPEARANCE: VERTICAL *****/\n"+
	 "/*}}}*/";
store.addNotification("StyleSheetDropDownMenuPlugin",refreshStyles);
//!END-PLUGIN-CODE
// %/
說了又不聽→聾,聽了又不懂→笨,不懂又不問→啞,問了又不做→懶,做了又做錯→蠢,錯了又不認→瞎,認了又不改→驢,改了又不服→爛,不服又不說→賤
本文網址 : http://www.ithome.com.tw/itadm/article.php?c=58584

於今年10月底發布的Ubuntu 9.10,預設磁碟的檔案系統格式為EXT 4,並首度內建檔案分享與同步服務,名為Ubuntu One。

與先前的9.04版一樣,這個版本同時有Desktop、Server與Netbook Remix版等3種版本,主要差別在於操作介面,以及適用環境的不同。而我們測試的Ubuntu 9.10 Desktop,是針對一般桌上型與筆記型電腦發行的版本,具有豐富的圖形介面,也有完整的文書、網路與影音功能。

Ubuntu 9.10所使用的系統核心,是目前最新的2.6.31,這個版本增加了支援ATI Radeon系列顯示卡的設定,也因此使用者不必為了ATI顯示卡的驅動而困擾。另外,這個系統核心也支援USB 3.0與Firewire等周邊介面。

改變搭配的輸入法平臺與軟體管理工具
在功能上,9.10版與舊版本雖然差異不大,不過許多內建的程式與軟體都有所改變,例如即時通訊軟體由Pidgin改為Empathy。這個新的即時通訊軟體內建15種通訊協定,包含MSN、Yahoo、Google Talk、QQ,以及比較少見的GroupWise等。

在輸入法方面,新版改為多語輸入法平臺的iBus,捨棄9.04版所內建的SCIM。iBus這個輸入法平臺比先前的SCIM更加穩定,且內建的中文輸入法為拼音、注音與倉頡等11種輸入法。如果需要其他語系的輸入法,我們只要在iBus設定即可。

[img[img/910/input.jpg]]

Ubuntu 9.10輸入法改用iBus輸入平臺,相較於先前版本內建的SCIM更加穩定。

另外,原本系統內建的軟體管理工具Ubuntu Tweak,到了9.10版,則改為Ubuntu軟體中心(Software Center)。

我們可以透過這套管理工具新增、移除程式之外,它也將軟體依照性質分類,分為影音、教育、系統工具與辦公等,方便搜尋所需要的功能。

安裝Ubuntu 9.10的過程,與先前版本並沒有太大的差異,不同的地方在於這個版本預設的磁碟格式為EXT 4。若使用手動安裝,一樣可以選擇EXT 3與EXT 2的磁碟格式。

事實上,採用不同的檔案系統格式的確會影響系統執行的速度。我們使用和測試9.04版時相同的硬體,並使用預設的EXT 4格式全新安裝作業系統並啟動之後,結果發現9.10版的開機時間約為35秒,比9.04版預設使用EXT 3格式所需的51秒,快上許多。

[img[img/910/softcenter.jpg]]

9.10版內建Ubuntu軟體中心,操作時可直接依照軟體性質的分類,搜尋所需要的功能,並直接下載。

提供免費線上儲存空間
這個版本新增的免費線上空間服務的Ubuntu One,它與另一種同步軟體DropBox非常相似,我們可以將需要同步、備份的檔案放在這個資料夾中,連接網路之後,就可以把資料備份到線上網路空間。目前這個服務提供2GB免費空間,如果需要更大的儲存空間,可付費擴充。此外,目前這個服務所支援的作業系統僅有Ubuntu。文⊙林柏凱 

<<importTiddlers inline>>
<<exportTiddlers inline>>
/***
|''Name:''|LaunchApplicationPlugin|
|''Author:''|Lyall Pearce|
|''Source:''|http://www.Remotely-Helpful.com/TiddlyWiki/LaunchApplication.html|
|''License:''|[[Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''Version:''|1.4.0|
|''~CoreVersion:''|2.3.0|
|''Requires:''| |
|''Overrides:''| |
|''Description:''|Launch an application from within TiddlyWiki using a button|
!!!!!Usage
<<<
{{{<<LaunchApplication "buttonLabel" "tooltip" "application" ["arguments" ...]>>}}}
{{{<<LaunchApplicationButton "buttonLabel" "tooltip" "application" ["arguments" ...]>>}}}
{{{<<LaunchApplicationLink "buttonLabel" "tooltip" "application" ["arguments" ...]>>}}}
* buttonLabel is anything you like
* tooltip is anything you like
* application is a path to the executable (which is Operating System dependant)
* arguments is any command line arguments the application requires.
* You must supply relative path from the location of the TiddlyWiki OR a fully qualified path
* Forward slashes works fine for Windows

{{{<<LaunchApplication...>>}}} functions the same as {{{<<LaunchApplicationButton...>>}}}

eg.

{{{
<<LaunchApplicationButton "Emacs" "Linux Emacs" "file:///usr/bin/emacs">>
}}}
<<LaunchApplicationButton "Emacs" "Linux Emacs" "file:///usr/bin/emacs">>

{{{
<<LaunchApplicationLink "LocalProgram" "Program relative to Tiddly html file" "localDir/bin/emacs">>
}}}
<<LaunchApplicationLink "LocalProgram" "Program relative to Tiddly html file" "localDir/bin/emacs">>
					     
{{{
<<LaunchApplicationButton "Open Notepad" "Text Editing" "file:///e:/Windows/notepad.exe">>
}}}
<<LaunchApplicationButton "Open Notepad" "Text Editing" "file:///e:/Windows/notepad.exe">>

{{{
<<LaunchApplicationLink "C Drive" "Folder" "file:///c:/">>
}}}
<<LaunchApplicationLink "C Drive" "Folder" "file:///c:/">>


!!!!!Revision History
* 1.1.0 - leveraged some tweaks from from Bradly Meck's version (http://bradleymeck.tiddlyspot.com/#LaunchApplicationPlugin) and the example text.
* 1.2.0 - Make launching work in Linux too and use displayMessage() to give diagnostics/status info.
* 1.3.0 - execute programs relative to TiddlyWiki html file plus fix to args for firefox.
* 1.3.1 - parameters to the macro are properly parsed, allowing dynamic paramters using {{{ {{javascript}} }}} notation.
* 1.4.0 - updated core version and fixed empty tooltip and added launch link capability
***/
<<tabs txtMoreTab "05" "05" LPIC101-005 "21" "21" LPIC101-021 "25" "25" LPIC101-025 "31" "31" LPIC101-031 "35" "35" LPIC101-035 "36" "36" LPIC101-036 "37" "37" LPIC101-037 "38""38" LPIC101-038 "34" "34" LPIC101-034 "42" "42" LPIC101-042 "43" "43" LPIC101-043 "53" "53" LPIC101-053 "60" "60" LPIC101-060 "66" "66" LPIC101-066 "70" "70" LPIC101-070 "71" "71" LPIC101-071 "72" "72" LPIC101-072 "73" "73" LPIC101-073 "74" "74" LPIC101-074 "75" "75" LPIC101-075 "76" "76" LPIC101-076 "77" "77" LPIC101-077 "80" "80" LPIC101-080 "83" "83" LPIC101-083 "85" "85" LPIC101-085>>

<<tabs txtMoreTab "92" "92" LPIC101-092 "94" "94" LPIC101-094 "126" "126" LPIC101-126 "130" "130" LPIC101-130>>
當時公司招了大批應屆本科和研究生畢業的新新人類。平均年齡25歲。那個新的助理,是經過多次面試後,我親自招回來的一個女孩。名牌大學本科畢業,聰明,性格活潑。私下裡我得承認,我招她的一個很重要的原因,除了她在大學裡優秀的表現之外,還因為她寫了一手漂亮的字。女孩能寫一手好字的不多,尤其像她,看起來長髮飄飄,多麼女性化的一個姑娘,一手字卻寫的鏗鏘倜儻,讓我對她不由多了很多好感。   

  手把手的教。從工作流程到待人接物。她也學的快。很多工作一教就上手。一上手就熟練。跟各位同事也相處的頗融洽。我開始慢慢的給她一些協調的工作,各部門之間以及各分公司之間的業務聯繫和溝通讓她嘗試著去處理。
  
  開始經常出錯。她很緊張,來找我談。我告訴她:錯了沒關係,你且放心按照你的想法去做。遇到問題了,來問我,我會告訴你該怎麼辦。仍然錯。又來找我,這次談的比較深入,她的困惑是,為什麼總是讓她做這些瑣碎的事情?我當時問她:什麼叫做不瑣碎的工作呢?

  她答不上來,想了半天,跟我說:我總覺得,我的能力不僅僅能做這些,我還能做一些更加重要的事情。那次談話,進行了1小時。我知道,我說的話,她沒聽進去多少。後來我說,先把手頭的工作做好,先避免常識性錯誤的發生。然後循序漸進罷。
  
  半年以後,她來找我,第一次提出辭職。我推掉了約會,跟她談辭職的問題。問起辭職的原因,她跟我直言:本科四年,功課優秀,沒想到畢業後找到了工作,卻每天處理的都是些瑣碎的事情。沒有成就感。我又問她:你覺得,在你現在所有的工作中,最沒有意義的最浪費你的時間精力的工作,是什麼?她馬上答我:幫您貼發票,然後報銷,然後到財務去走流程,然後把現金拿回來給您。
  
  我笑著問她:你幫我貼發票報銷有半年了吧?通過這件事兒,你總結出了一些什麼資訊?
  
  她呆了半天,答我:貼發票就是貼發票,只要財務上不出錯,不就行了唄,能有什麼資訊?
  
  我說,我來跟你講講,當年我的做法吧:98年的時候,我從財務被調到了總經理辦公室,擔任總經理助理的工作。其中有一項工作,就是跟你現在做的一樣,幫總經理報銷他所有的票據。本來這個工作就像你你剛才說的,把票據貼好,然後完成財務上的流程,就可以了。

  其實票據是一種資料記錄,它記錄了和總經理乃至整個公司營運有關的費用情況。看起來沒有意義的一堆資料,其實它們涉及到了公司各方面的經營和運作。於是我建立了一個表格,將所有總經理在我這裡報銷的資料按照時間,數額,消費場所,連絡人,電話等等記錄下來。

  我起初建立這個表格的目的很簡單,我是想在財務上有據可循,同時萬一我的上司有情況來詢問我的時候,我會有準確的資料告訴他。通過這樣的一份資料統計,漸漸的我發現了一些上級在商務活動中的規律,比如,哪一類的商務活動,經常在什麼樣的場合,費用預算大概是多少;總經理的公共關係常規和非常規的處理方式。等等等等。

  當我的上級發現,他佈置工作給我的時候,我會處理的很妥貼。有一些資訊是他根本沒有告訴我的,我也能及時準確的處理。他問我為什麼,我告訴了他我的工作方法和資訊來源。

    漸漸的,他基於這種良性積累,越來越多的交待更加重要的工作。再漸漸的,一種信任和默契就此產生,我升職的時候,他說我是他用過的最好用的助理。
  
  說完這些長篇大論,我看著這個姑娘,她愣愣的看著我。我跟她直言:我覺得你最大的問題,是你沒有用心。在看似簡單不動腦子就能完成的工作裡,你沒有把你的心沉下去,所以,半年了,你覺得自己沒有進步。她不出聲。但是收回了辭職報告。
  
  又堅持了3個月,她還是辭職了。這次我沒有留她。讓她走了。

  後來她經常在MSN上跟我聊天。告訴我她的新工作的情況。一年內,她換了三份工作。每一次都堅持不了多久。每一次她都說新的工作不是她想要的工作。05年的時候,她又一次辭職了。很苦惱,跑來找我,要跟我吃飯。我請她去寫字樓後面的商場吃日本料理。吃到中途,忽然跟我說:我有些明白你以前說的話是什麼意思了。 
<<tabs txtMoreTab "04" "04" LPIC101-004 "10" "10" LPIC101-010 "116" "116" LPIC101-116>>
目前現有的協作產品如微軟自家SharePoint、IBM Lotus等,都需部署伺服器,檔案要透過伺服器存取。不過走P2P架構的Groove,檔案就存在使用者電腦。

微軟去年推出Office 2007產品線旗下的協同作業平台Groove,六月將有文版產品,和先前推出協作平台SharePoint不同的是,Groove走的是P2P架構,不需部署伺服器。

Groove在去年推出Office 2007時就已包含在內,不過只有英文版本。目前在商用版、旗鑑版當中都附有Groove,也可單買。

台灣微軟營運暨行銷事業群資深產品行銷經理盧道正指出,Groove是文件分享的協作工具,此產品的特殊之處在於採用P2P架構。目前現有的協作產品如微軟自家SharePoint、IBM Lotus等,都需部署伺服器,檔案要透過伺服器存取。不過走P2P架構的Groove,檔案就存在使用者電腦。

盧道正說,雖然同是協作軟體,但Groove和SharePoint並不會有衝突,因為Groove適合多對多的應用,而SharePoint則適合一對多,並不會造成自家產品互打的狀況。

微軟在上月(3/17)針對學生族群引進國外的校園低價專案時,同時宣佈推出含有Groove的Office旗鑑版本。由於不需部署伺服器,可簡單的連線使用,因此微軟也希望藉由校園專案將Groove推向學生族群。

這也是Groove和SharePoint的區隔,因為部署簡單,所以不僅可用於企業內部文件分享、討論,學生在進行團體報告時也可以 Groove搭配Office使用。而且價格低廉,透過學生專案購買含有Groove的旗鑑版Office為1990元;而在六月中文版推出後,以單一產品購買要五千多元。

消費端檔案分享產品暫不引進台灣

除了企業端協作軟體外,微軟本月(4)也在國外正式發表針對消費市場的Office Live Workspace,不過目前暫無打算引進台灣。

盧道正澄清,Office Live Workspace並不能算是「線上版」的Office,使用者電腦中還是必須裝有文書處理軟體,Office Live Workspace只是進行檔案分享,如同協作平台,並可共用螢幕。

Office Live Workspace走的也是伺服器架構,不過是微軟針對消費端的產品,SharePoint則是主攻企業端。對於微軟上週(4/18)開始進行封閉測試、代號為Albany的生產力軟體套件,台灣微軟則表示並不清楚。
網址 : http://www.ithome.com.tw/itadm/article.php?c=73177

有鑑於微軟長期以來致力於推動私有技術,而且曾與開放社群格格不入,使得不少分析師質疑微軟設立Microsoft Open Technologies子公司的意圖。

微軟周四(4/12)宣布成立由微軟握有百分之百股權的子公司Microsoft Open Technologies,公司宗旨為強化微軟在互通性、開放標準及開放源碼上的投資。

XML發明人之一、微軟互通性策略總經理Jean Paoli將擔任新公司的總裁。Paoli表示,互通性策略團隊一向與微軟內部各種攸關開放標準的專案團隊合作密切,例如W3C的HTML 5、IETF的HTTP 2.0,或是DMTF與OASIS的雲端標準,以及Node.js、MongoDB與Phonegap/Cordova等,因此,該團隊也將成為新公司的核心。

Paoli說明,Microsoft Open Technologies將以更清楚的方式提供與開放社群合作的模式,此一全新架構將協助推動微軟私有開發程序、微軟各種開放創新成果以及開放社群之間的互動。該架構將更容易並更快釋出開放源碼軟體、參與既有的開放源碼專案,以及接受來自社群的貢獻,經年累月將能看到該公司與開放世界間更緊密的交互影響。

即使設立新公司來推動開放標準與開放源碼,但Paoli強調微軟各部門仍將持續以不同的方式與開放標準及開放源碼社群交流,Microsoft Open Technologies只是進一步展現了微軟對互通性與開放的長期承諾。藉由Microsoft Open Technologies的成立,微軟客戶亦會有更多的選擇與機會於異質環境中橋接微軟與非微軟的產品。

有鑑於微軟長期以來致力於推動私有技術,而且曾與開放社群格格不入,使得不少分析師質疑微軟的意圖,有分析師認為微軟也許只是想隔離公司內部的開放源碼與私有技術,以避免可能引起的授權或專利糾紛。(編譯/陳曉莉) 

<<tabs txtMoreTab "17" "17" LPIC101-017 "18" "18" LPIC101-018 "06" "06" LPIC101-006 "07" "07" LPIC101-007 "30" "30" LPIC101-030 "33" "33" LPIC101-033 "59" "59" LPIC101-059 "67" "67" LPIC101-067 "69" "69" LPIC101-069 "79" "79" LPIC101-079 "88" "88" LPIC101-088 "93" "93" LPIC101-093 "96" "96" LPIC101-096 "99" "99" LPIC101-099 "113" "113" LPIC101-113 "127" "127" LPIC101-127 "134" "134" LPIC101-134 "19" "19" LPIC101-019 "129" "129" LPIC101-129>>
<<tabs txtMoreTab "11" "11" LPIC101-011 "32" "32" LPIC101-032 "44" "44" LPIC101-044 "45" "45" LPIC101-045 "46" "46" LPIC101-046 "51" "51" LPIC101-051 "55" "55" LPIC101-055 "58" "58" LPIC101-058 "78" "78" LPIC101-078 "81" "81" LPIC101-081 "95" "95" LPIC101-095 "97" "97" LPIC101-097 &qu