Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
scripting:processtree [2010/04/21 21:14]
127.0.0.1 external edit
scripting:processtree [2018/07/24 18:18] (current)
csb [Bash playing with pipes] typo fix
Line 5: Line 5:
 ===== The process tree ===== ===== The process tree =====
  
-The processes in UNIX(r) are - unlike ​in other systems ​you may have seen - **organized ​in a tree**. Every process has a parent process that started ​it or is responsible for it. Also, every process has an own **context memory** (I don't mean the memory where the process stores its data, I mean memory where data is stored that doesn'​t directly belong to the process, but is needed to run the process)__**The environment**__.+The processes in UNIX(r) are - unlike other systems - **organized ​as a tree**. Every process has a parent process that startedor is responsiblefor it. Every process has its own **context memory** (Not the memory where the process stores its data, rather, the memory where data is stored that doesn'​t directly belong to the process, but is needed to run the process) ​i.e. __**The environment**__.
  
-To make it really clear I want to repeat it: Every process has its **own** environment space.+Every process has its **own** environment space.
  
-The environment stores, ​beside ​other stuff, data that's useful ​for usThe **environment variables**. These are strings in the common ''​NAME=VALUE''​ form, but they are not related to shell variables. A variable named ''​LANG'',​ for example, is used by every program that looks it up in its environment to determinate the current locale.+The environment stores, ​among other things, data that's useful ​to usThe **environment variables**. These are strings in common ''​NAME=VALUE''​ form, but they are not related to shell variables. A variable named ''​LANG'',​ for example, is used by every program that looks it up in its environment to determinate the current locale.
  
-**__Attention:​__** A variable that is set, like with ''​MYVAR=Hello'',​ is **not** automatically part of the environment. You need to put it into the environment with the ''​export'' ​utility:+**__Attention:​__** A variable that is set, like with ''​MYVAR=Hello'',​ is **not** automatically part of the environment. You need to put it into the environment with the bash builtin command ​''​export'':​
 <​code>​export MYVAR</​code>​ <​code>​export MYVAR</​code>​
-Common system variables like ''​PATH'' ​or ''​HOME''​ usually already ​are part of the environment (as set by login scripts or programs).+Common system variables like [[syntax:​shellvars#​PATH|PATH]] ​or [[syntax:​shellvars#​HOME|HOME]] ​are usually ​part of the environment (as set by login scripts or programs).
  
 ===== Executing programs ===== ===== Executing programs =====
  
-All the diagrams of the process tree use names like "''​xterm''"​ or "''​bash''",​ but that's just for you to understand what's going on, it doesn'​t mean it really runs processes ​with these names.+All the diagrams of the process tree use names like "''​xterm''"​ or "''​bash''",​ but that's just to make it easier ​understand what's going on, it doesn'​t mean those processes ​are actually executed.
  
-Let's take a short look what happens when you "​execute a program"​ from the Bash prompt, a program like "​ls":​+Let's take a short look at what happens when you "​execute a program"​ from the Bash prompt, a program like "​ls":​
  
 <​code>​ <​code>​
Line 34: Line 34:
 xterm ----- bash ----- bash(copy) xterm ----- bash ----- bash(copy)
 </​code>​ </​code>​
-...and after the "​second Bash" (the copy) replaced ​itself ​by the ''​ls''​-program (it execs it), it might look like+...and after the "​second Bash" (the copy) replaces ​itself ​with the ''​ls''​ program (the copy execs it), it might look like
 <​code>​ <​code>​
 xterm ----- bash ----- ls xterm ----- bash ----- ls
 </​code>​ </​code>​
  
-If everything was okay, the two steps resulted in one program being ran. The copy of the environment from the first step (forking) ​results in the environment for the final running program (''​ls'' ​in this case).+If everything was okay, the two steps resulted in one program being run. The copy of the environment from the first step (forking) ​becomes ​the environment for the final running program (in this case, ''​ls''​).
  
-__**What is so important about it?​**__ ​Well, in our example, ​whatever ​the program ''​ls'' ​will do inside its own environment,​ it can'​t ​have any effect to the environment of its parent process (''​bash'' ​here). The environment was copied when ls was executed. ​**That'​s a one-way!** ​Nothing ​will "copy it back" when ''​ls''​ terminates!+__**What is so important about it?​**__ ​In our example, ​what the program ''​ls'' ​does inside its own environment,​ it can'​t ​affect ​the environment of its parent process (in this case, ''​bash''​). The environment was copied when ls was executed. Nothing ​is "copied ​back" ​to the parent environment ​when ''​ls''​ terminates.
  
 ===== Bash playing with pipes ===== ===== Bash playing with pipes =====
  
-Pipes are a very powerful tool. You can connect the out- and inputstreams ​of two separate programs, and thus create a new utility - or better: a new functionalityWell, we're not here to explain ​piping, we just want to see how they look in the process tree. Again, we execute some commands ​''​ls''​ and ''​grep'':​+Pipes are a very powerful tool. You can connect the output ​of one process to the input of another processWe won't delve into piping ​at this point, we just want to see how it looks in the process tree. Again, we execute some commands, this time, we'll run ''​ls''​ and ''​grep'':​
  
 <​code>​ <​code>​
Line 58: Line 58:
 </​code>​ </​code>​
  
-Just to be boring ​again''​ls''​ can't influence the environment of ''​grep''​''​grep''​ can't influence the environment of ''​ls'',​ neither ''​grep''​ nor ''​ls''​ can influence the environment of ''​bash''​.+Note once again''​ls''​ can't influence the ''​grep'' ​environment. ​''​grep''​ can't influence the ''​ls'' ​environmetand neither ''​grep''​ nor ''​ls''​ can influence the ''​bash'' ​environment.
  
 __**How is that related to shell programming?​!?​**__ __**How is that related to shell programming?​!?​**__
  
-Well, imagine some Bash-code that reads data from a pipe. Let's take the internal command ''​read'',​ which reads data from //stdin// and puts it into a variable. We run it in a loop here - we count input lines...:+Well, imagine some Bash code that reads data from a pipe. For example, ​the internal command ''​read'',​ which reads data from //stdin// and puts it into a variable. We run it in a loop here to count input lines:
  
 <​code>​ <​code>​
 counter=0 counter=0
-cat /etc/passwd | while read LINE; do ((counter++));​ done + 
-echo Lines: $counter+cat /etc/passwd | while read; do ((counter++));​ done 
 +echo "Lines: $counter"
 </​code>​ </​code>​
  
 What? It's 0? Yes! The number of lines might not be 0, but the variable ''​$counter''​ still is 0. Why? What? It's 0? Yes! The number of lines might not be 0, but the variable ''​$counter''​ still is 0. Why?
-Remember the diagram from above? ​I'll rewrite ​it a bit:+Remember the diagram from above? ​Rewriting ​it a bit, we have:
 <​code>​ <​code>​
                    +-- cat /etc/passwd                    +-- cat /etc/passwd
 xterm ----- bash --| xterm ----- bash --|
-                   +-- bash (while read LINE; do ((counter++));​ done)+                   +-- bash (while read; do ((counter++));​ done)
 </​code>​ </​code>​
  
-See the relation? The forked Bash will count the lines like a charm. It will also set the variable ''​counter'' ​like you wanted it. But if everything ends, this extra process will be terminated - **your variable is gone** ​- R.I.P. ​You see a 0 because in the main shell it always ​was 0 and never something else!+See the relationship? The forked Bash process ​will count the lines like a charm. It will also set the variable ''​counter'' ​as directed. But if everything ends, this extra process will be terminated - **your ​"​counter" ​variable is gone** You see a 0 because in the main shell it was 0and wasn't changed by the child process!
  
-__**Aha! And now, how to count those lines?​**__ +__**So, how do we count the lines?​**__ 
-Easy: **Avoid the subshell.** ​How you do it in detail doesn't matter, the important thing is that the shell that sets the counter must be the "main shell"​. For example ​do it like this:+Easy: **Avoid the subshell.** ​The details don't matter, the important thing is the shell that sets the counter must be the "main shell"​. For example:
  
 <​code>​ <​code>​
 counter=0 counter=0
-while read LINE; do ((counter++));​ done </​etc/​passwd + 
-echo Lines: $counter+while read; do ((counter++));​ done </​etc/​passwd 
 +echo "Lines: $counter"
 </​code>​ </​code>​
  
-It's nearly self-explaining. The ''​while''​-loop runs in the **current shell**, the counter is increased ​in the **current shell**, everything vital happens in the **current shell**, also the ''​read''​-command sets the variable ''​LINE'',​ though we don't use it here, it's just a dummy. This small script should work.+It's nearly self-explanitory. The ''​while''​ loop runs in the **current shell**, the counter is incremented ​in the **current shell**, everything vital happens in the **current shell**, also the ''​read''​ command sets the variable ''​REPLY'' ​(the default if nothing is given), though we don't use it here.
  
 ===== Actions that create a subshell ===== ===== Actions that create a subshell =====
Line 99: Line 101:
 As shown above, Bash will create subprocesses everytime it executes commands. That's nothing new. As shown above, Bash will create subprocesses everytime it executes commands. That's nothing new.
  
-But imagine ​your command ​actually ​is a script ​that sets variables you want to use in your main script. This won't work.+But if your command is a subprocess ​that sets variables you want to use in your main script, that won't work.
  
-For exactly this purpose, there'​s the ''​source''​ command (also: the //dot// ''​.''​ command). ​It doesn'​t ​really actually ​execute the script ​like it would execute any other program - it's more like including ​the other script'​s ​source ​code into the current shell:+For exactly this purpose, there'​s the ''​source''​ command (also: the //dot// ''​.''​ command). ​Source ​doesn'​t execute the scriptit imports ​the other script'​s code into the current shell:
 <​code>​ <​code>​
 source ./​myvariables.sh source ./​myvariables.sh
Line 110: Line 112:
 ==== Pipes ==== ==== Pipes ====
  
-The last big section was about pipes, so no example here...+The last big section was about pipes, so no example here.
 ==== Explicit subshell ==== ==== Explicit subshell ====
  
Line 117: Line 119:
 ==== Command substitution ==== ==== Command substitution ====
  
-With [[syntax:​expansion:​cmdsubst | command substitution]] you re-use the output of another command as text in your commandline, for example to set a variable. ​This other command is run in a subshell: +With [[syntax:​expansion:​cmdsubst | command substitution]] you re-use the output of another command as text in your command line, for example to set a variable. ​The other command is run in a subshell: 
-<​code>​NUMBER_OF_USERS=$(cat /etc/passwd | wc -l)</​code>​ +<​code>​number_of_users=$(cat /etc/passwd | wc -l)</​code>​ 
-Note that, in this example, ​you create ​a second subshell by using a pipe in the command substitution ​(just as sidenote):+Note that, in this example, ​ a second subshell ​was created ​by using a pipe in the command substitution:​
 <​code>​ <​code>​
                                             +-- cat /etc/passwd                                             +-- cat /etc/passwd
  • scripting/processtree.1271884448.txt
  • Last modified: 2010/12/20 03:00
  • (external edit)