Differences

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

Link to this comparison view

ii:labs:01:tasks:02 [2021/10/08 23:48]
radu.mantu [02. [40p] tmux]
ii:labs:01:tasks:02 [2024/10/18 12:14] (current)
radu.mantu
Line 3: Line 3:
 **tmux** is a terminal multiplexer. It allows you to split a terminal into multiple views on the same screen, create multiple sessions, etc. **tmux** is a terminal multiplexer. It allows you to split a terminal into multiple views on the same screen, create multiple sessions, etc.
  
 +[[https://​ocw.cs.pub.ro/​courses/​_media/​ii/​labs/​01/​tasks/​tmux-demo.gif|{{ :​ii:​labs:​01:​tasks:​tmux-demo.gif?​700 |}}]]
 +<​html><​center><​i>​ Click GIF to maximize. </​i></​center></​html>​
  
 One particularly interesting feature is that you can detach yourself from a session only to reattach later. Take the following scenario: you need to start a process on a remote machine once you **ssh** into it. The process needs to keep running even after you exit. How do you launch that process? One particularly interesting feature is that you can detach yourself from a session only to reattach later. Take the following scenario: you need to start a process on a remote machine once you **ssh** into it. The process needs to keep running even after you exit. How do you launch that process?
Line 13: Line 15:
   * ''​nohup'':​ works in the same way as **sudo** but doesn'​t give you administrative privileges. In stead, what it does is that it makes the process that you launch //immune// to hangup signals. When your controlling process dies (in this case your very terminal), its children get a hangup signal that is automatically handled by causing them to immediately die. **nohup** allows those children to ignore the signal and keep on living.   * ''​nohup'':​ works in the same way as **sudo** but doesn'​t give you administrative privileges. In stead, what it does is that it makes the process that you launch //immune// to hangup signals. When your controlling process dies (in this case your very terminal), its children get a hangup signal that is automatically handled by causing them to immediately die. **nohup** allows those children to ignore the signal and keep on living.
   * ''<​INPUT_FILE'':​ when the terminal dies, your //stdin//, //stdout// and //stderr// are gone as well. Even if the children survive their parent'​s death, reading or writing to any of these three "​files"​ will cause an error. In other words they still die, just less gracefully. If you know that your process never reads from //stdin//, you can skip this. Otherwise, it's a good idea to redirect the input from a file that you know will persist, such as a storage-backed file.   * ''<​INPUT_FILE'':​ when the terminal dies, your //stdin//, //stdout// and //stderr// are gone as well. Even if the children survive their parent'​s death, reading or writing to any of these three "​files"​ will cause an error. In other words they still die, just less gracefully. If you know that your process never reads from //stdin//, you can skip this. Otherwise, it's a good idea to redirect the input from a file that you know will persist, such as a storage-backed file.
-  * ''&>​OUTPUT_FILE'':​ the explanation above applies here as well. ''&''​ is just a shorthand for both //stdout// and //stderr//. So you redirect both to the same file. Note that this file (or that that replaces stdin, for that matter) can be// /dev/null// or// /dev/zero. // +  * ''&>​OUTPUT_FILE'':​ the explanation above applies here as well. ''&''​ is just a shorthand for both //stdout// and //stderr//. So you redirect both to the same file. Note that this file (or that which replaces stdin, for that matter) can be// /dev/null// or// /dev/zero. // 
-  * ''&'':​ this final component of our command tells our shell to start the process in background, not needing to put the parent (i.e.: **zsh** or **bash**) on-hold until it finishes.+  * ''&'':​ this final component of our command tells our shell to start the process in background, not needing to pester ​the parent (i.e.: **zsh** or **bash**), putting it on-hold until it finishes.
  
-Pretty complicated,​ right? And even if you do this, when you start a new SSH session it will be //very// difficult to change these parameters (e.g.: redirecting //stdout// to your terminal). I bet **tmux** looks pretty good right about now :)+Pretty complicated,​ right? And even if you do this, when you start a new SSH session it will be //very// difficult to change these parameters (e.g.: redirecting //stdout// to your terminal) ​while the process is running. I bet **tmux** looks pretty good right about now :)
  
 === [10p] Task A - Installation === === [10p] Task A - Installation ===
  
-This is a lot less painful than it was for **zsh**, so don't worry. ​So let's install **tmux** and run it:+This is a lot less painful than it was for **zsh**, so don't worry. ​Let's install **tmux** and run it:
  
 <​code>​ <​code>​
Line 34: Line 36:
   * //<Ctrl + B> "// : split terminal vertically   * //<Ctrl + B> "// : split terminal vertically
   * //<Ctrl + B> ←↑↓→//​ : cycle through active terminals   * //<Ctrl + B> ←↑↓→//​ : cycle through active terminals
 +  * //<Ctrl + B + ←↑↓→>//​ : resize active terminals
  
 Note that you can rebind all these shortcuts in a config file. For now, let's add a rather useful option: allowing to switch active shell by clicking on it. Also, the color of the **zsh** auto-completion plugin might have defaulted to white; let's fix this as well. Note that you can rebind all these shortcuts in a config file. For now, let's add a rather useful option: allowing to switch active shell by clicking on it. Also, the color of the **zsh** auto-completion plugin might have defaulted to white; let's fix this as well.
Line 42: Line 45:
 $ tmux source-file ~/​.tmux.conf $ tmux source-file ~/​.tmux.conf
 </​code>​ </​code>​
 +</​note>​
 +
 +<note important>​
 +If you are working in a Virtual Machine, it may be unable to capture key combinations such as //<Ctrl + B>//. There are two alternatives to using these shortcuts.
 +  - right click on the terminal (while running tmux) and drag the mouse. A menu should appear with some basic commands. Drag the cursor over the command and release the mouse button
 +  - run ''​tmux split-window''​. This command shows all configured binds. We notice the ''​split-window [-h]''​ command being used, so try running ''​tmux split-window''​ with a **tmux** instance already running. This will send it a split screen request, just like //<Ctrl + B> "//.
 </​note>​ </​note>​
  
Line 59: Line 68:
 === [10p] Task C - Start tmux by default === === [10p] Task C - Start tmux by default ===
  
-If you open a new terminal with //<Ctrl + Alt + T>// you will notice that **tmux** is not running. When **zsh** starts up, it automatically sources //.zshrc//, so lets make it execute **tmux** by adding the following at the end:+If you open a new terminal with //<Ctrl + Alt + T>// you will notice that **tmux** is not running. When **zsh** starts up, it automatically sources //.zshrc//, so let'​s ​make it execute **tmux** by adding the following at the end:
  
 <​code>​ <​code>​
 # start tmux session (only once!) # start tmux session (only once!)
-if [ -z "​$TMUX"​ ] && [[ "​$USER"​ == "<YOUR_USERNAME_GOES_HERE>" ]]; then+if [ -z "​$TMUX"​ ] && [[ "​$USER"​ == "​YOUR_USERNAME_GOES_HERE"​ ]]; then
     exec tmux     exec tmux
 fi fi
 </​code>​ </​code>​
  
-This may require some explanations:+This may require some explanations. If at any point you're feeling lost, check out the diagram in the spoiler below (or ask).
   * ''​[ -z "​$TMUX"​ ]'':​ Your shell defines some //​environment variables// which can be seen by running the ''​env''​ command. Unless you have an active **tmux** session, there is no //TMUX// variable. So if that variable is empty (which in **bash** / **zsh** means it doesn'​t exist), we need to start **tmux**. But remember! **tmux** then starts your default shell (i.e.: **zsh**), which sources //.zshrc// again, and executes **tmux**... again... See where I'm going with this? You run into an infinite loop of starting **tmux** and **zsh** and your terminal will simply crash. So we need to start **tmux** __exactly__ once.   * ''​[ -z "​$TMUX"​ ]'':​ Your shell defines some //​environment variables// which can be seen by running the ''​env''​ command. Unless you have an active **tmux** session, there is no //TMUX// variable. So if that variable is empty (which in **bash** / **zsh** means it doesn'​t exist), we need to start **tmux**. But remember! **tmux** then starts your default shell (i.e.: **zsh**), which sources //.zshrc// again, and executes **tmux**... again... See where I'm going with this? You run into an infinite loop of starting **tmux** and **zsh** and your terminal will simply crash. So we need to start **tmux** __exactly__ once.
-  * ''​%%[[%% "​$USER"​ == "​..."​ %%]]%%'':​ This is a solution for a rather dumb problem. Up until now, you've set up **zsh** only for your user but not for //root//. If you create// /​root/​.zshrc//​ and in it you just source the main //.zshrc// in your home, you will end up executing **tmux** again, but only once more. The reason is that the //TMUX// environment variable is not passed to the new user's shell. Why this is annoying is that the second **tmux** instance will add another status bar to the bottom of your screen. Normally, when you start a terminal with //<Ctrl + Alt + T>// you don't run a shell root, so this workaround is somewhat valid.+  * ''​%%[[%% "​$USER"​ == "​..."​ %%]]%%'':​ This is a solution for a rather dumb problem. Up until now, you've set up **zsh** only for your user but not for //root//. If you create// /​root/​.zshrc//​ and in it you just source the main //.zshrc// in your home, you will end up executing **tmux** again, but only once more. The reason is that the //TMUX// environment variable is not passed to the new user's shell. Why this is annoying is that the second **tmux** instance will add another status bar to the bottom of your screen. Normally, when you start a terminal with //<Ctrl + Alt + T>// you don't run a shell as //root//, so this workaround is somewhat valid.
   * ''​exec tmux'':​ By running ''​tmux''​ you will be able to ''​exit''​ or //<Ctrl + D>// and you'll return to the original **zsh** shell. By running ''​exec tmux''​ you will effectively //replace// your current shell, so when you exit, you will close the entire terminal window.   * ''​exec tmux'':​ By running ''​tmux''​ you will be able to ''​exit''​ or //<Ctrl + D>// and you'll return to the original **zsh** shell. By running ''​exec tmux''​ you will effectively //replace// your current shell, so when you exit, you will close the entire terminal window.
  
- +<​spoiler>​ 
-TODOadd diagram+[[https://​ocw.cs.pub.ro/​courses/​_media/​ii/​labs/​01/​tasks/​tmux-zsh-flow.png|{{ :​ii:​labs:​01:​tasks:​tmux-zsh-flow.png?​500 |}}]] 
 +</​spoiler>​
  
 === [10p] Task D - Have some fun with it === === [10p] Task D - Have some fun with it ===
ii/labs/01/tasks/02.1633726109.txt.gz · Last modified: 2021/10/08 23:48 by radu.mantu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0