Wednesday, April 30, 2014

Unix Shell Basic(1)

1. Compiled Language and Script

Good part: Compared to compiled language, script is more easily to handle objects like files and directories. And it is much less costly to write the script than to write compiled language. Finally it is more easily to port the script to run in other machines.

Bad part: Compared to compiled language, running script is less efficient.

2. Run Simple Command:
 aubinxia@aubinxia-VirtualBox:~$ who  
 aubinxia :0      2014-04-30 14:26 (:0)  
 aubinxia pts/0    2014-04-30 14:28 (:0)  

3. Use Pipeline:
 aubinxia@aubinxia-VirtualBox:~$ who | wc -l  
 2  

In this case, command "who"'s output, which is 2 lines of text as showed above, will be fed into "wc" command as the input. wc will count how many lines the input has, output 2.

4. Put commands into script file
 aubinxia@aubinxia-VirtualBox:~/Desktop/xxdev$ cat > num_users  
 who | wc -l  
 aubinxia@aubinxia-VirtualBox:~/Desktop/xxdev$ ./num_users  
 bash: ./num_users: Permission denied  
 aubinxia@aubinxia-VirtualBox:~/Desktop/xxdev$ chmod +x ./num_users  
 aubinxia@aubinxia-VirtualBox:~/Desktop/xxdev$ ./num_users  
 2  
 aubinxia@aubinxia-VirtualBox:~/Desktop/xxdev$   

In this case, we firstly use cat to output the command into file named num_users.
After putting the command there, we typed "ctrl + D" to indicate end-of-file and quit the editing. Then we tried to run script, but found that it doesn't have the running permission. So we used "chmod" to add the execution permission and run num_users, get the output "2".

5. Use "Shell"
num_users:
 #! /bin/bash  
 who | wc -l  

The first line #! /bin/bash means, when the script is run, the system will use /bin/bash to run the script. It will run following command:
/bin/bash who | wc -l
And then output 2

Note:
1) while space in #! ... line is sensitive, need to refer to different flavor of unix product document
2) There is length limit for words after "#!", different unix implementation has different requirements
3) Need to adjust #! ... line if port the script to another machine, since different implementation put shell program in different path ( /usr/bin/bash...)

6. Official Commands Format

"-o" is option, obj.o is the argument of "-o". argument is optional in many commands:
 aubinxia@aubinxia-VirtualBox:~/Desktop/xxdev$ gcc -o obj.o  

many options without argument can be compiled into one option:
 aubinxia@aubinxia-VirtualBox:~/Desktop/xxdev$ ls -l -a  
 total 16  
 drwxrwxr-x 2 aubinxia aubinxia 4096 Apr 30 14:57 .  
 drwxr-xr-x 3 aubinxia aubinxia 4096 Apr 18 12:44 ..  
 -rwxrwxr-x 1 aubinxia aubinxia  32 Apr 30 14:57 num_users  
 -rwxrwxr-x 1 aubinxia aubinxia  25 Apr 30 14:54 num_users~  
 aubinxia@aubinxia-VirtualBox:~/Desktop/xxdev$ ls -la  
 total 16  
 drwxrwxr-x 2 aubinxia aubinxia 4096 Apr 30 14:57 .  
 drwxr-xr-x 3 aubinxia aubinxia 4096 Apr 18 12:44 ..  
 -rwxrwxr-x 1 aubinxia aubinxia  32 Apr 30 14:57 num_users  
 -rwxrwxr-x 1 aubinxia aubinxia  25 Apr 30 14:54 num_users~  

ls -l is "listing" all entries in current place. ls -a is trying to show all entries including "." "..". Since both options don't have argument, we can combine them together and we still get the same output.

"--"option may take option with more than one character, and such option is not allowed to have any arguments:
 aubinxia@aubinxia-VirtualBox:~/Desktop/xxdev$ ls --all  
 . .. num_users num_users~  
 aubinxia@aubinxia-VirtualBox:~/Desktop/xxdev$ ls --all obj  
 ls: cannot access obj: No such file or directory  

7. Run script asynchronously
 aubinxia@aubinxia-VirtualBox:~/Desktop/xxdev$ emacs num_users; ls 

Above script make user edit "num_users" script, if emacs doesn't exist, then system just stop in there, and "ls" will never be able to get run.

 aubinxia@aubinxia-VirtualBox:~/Desktop/xxdev$ emacs num_users & ls --all  
 [2] 3856  
 . .. num_users num_users~  
 [1]  Done          emacs num_users  

Above script opened num_users script file, at the same time, it lists all files under local place without waiting for "enum" to quit.

8. Fundamental Kinds of Commands:

1) Built-in Commands: like "cd". The commands that shell itself executes
2) Shell Functions: self-contained chunk of code written in shell languages
3) External Commands: existed in $PATH folders. Whenever unix run them, it need start a new process.

9. Shell Variables

 #! /bin/bash  
 var_bad_1 =Hello #error, we can NOT add additional space after variable name  
 var_bad_2=Hello world #error, We need to use double quote like var_3 if having space  
 var_1=Hello  
 var_2=world!  
 var_3="Hello world!"  
 var_4="$var_1 $var_2"  
 var_5=5  
 var_6=$var_5+$var_5 #it will just take var_5 as text, and var_6 is text too!  

 echo $var_1 #output Hello  
 echo $var_2 #output world!  
 echo $var_3 #output "Hello world!"  
 echo $var_4 #output "Hello world!"  
 echo $var_6 #output "5+5"  

10. echo

 #! /bin/bash  
 echo Hello  world!   
 # output "Hello world" with one space between. echo will output each object after it with only  
 # one space inserted between  

 echo -n Enter your name:  
 #it will remove the "newline" right after "Enter your name:", and the output will be right  
 #after that, instead of starting from a new line  

 echo Hello world \n Hello world  
 #output "Hello world n Hello world", if user want to use the escape sequence, it has to be  
 #in double quote  

 echo "Hello world!\n"  
 #still output "Hello world!\n", why?  
 #echo command is very infamous because of its non-portability. Different flavor of unix will  
 #totally different implementation of echo. Under current platform, echo looks like not supporting  
 #escape sequence  

11. standard output: printf

Because "echo" is not compatible across different unix implementation. "printf" is part of POSIX standard which make its behavior consistent across many unix implementations.

 #! /bin/bash  
 printf "Hello world!"   
 #output "Hello world!" without new line! note: echo add newline at the end by default  

 printf "Hello\nworld!\n"  
 #output:  
 #Hello  
 #world!  
 #printf allows to use escape sequence. "\n" indicates adding newline  

 printf "%d words: '%s %s'\n" 2 Hello world!  
 #output: 2 words: 'Hello world!'  
 #printf is using format specification here.   
 #"%d words: '%s %s'\n" is the foramt, "2", "Hello" "world!" are arguements which are  
 #going to be fed into the "%d, %s, %s". %d means integer, %s means string  

 printf "%d\n" Hello #output: ./test: line 18: printf: Hello: invalid number  
 printf "%s\n" 100 #output: 100  


Unix Operating System

1. Unix was developed in Bell Labs, a research-oriented environment. Users are mainly computer scientist in Bell Labs. All those stuff make unix very elegant, not chatty system.

2. Since every one in Bell Labs can change the system by themselves, which brings a lot of inconsistencies for many tools. A standard was formed in the end: POSIX.
All modern unix-like operating system, including GNU/Linux, BSD derived systems, they are all POSIX compliant.

3. Unix Principals:

1) Focus on one thing: each program or tool focus on one thing, making it easy to maintain, document, efficient.

2) Process Lines of Text not binary. Text is the main content for most unix tool to deal with, making lines of text universal language in Unix world.

3) Use regular expressions. Unix use most of the power of regular expressions. It tries to use 2 kinds of regular expressions: grep(Basic Regular Expressions or BREs per POSIX standard), egrep(Extended Regular Expressions or EREs per POSIX standard)

4) Default to standard I/O.If not providing the specific input/output, unix will read from standard input and output to standard output by default.

5) Elegant and not chatty. Since unix is built for well-educated computer scientists or engineers, it should always assume the user knows a lot, and all solutions it provides is very elegant and not chatty.

6) Reuse existing tools. If there is existing tool to solve a problem, it always use existing ones. If we need another specialized tool, the user need to build the tool from "a general picture", trying to make it be reused in the future.