Vỏ Bash

Giới thiệu người dùng về Bash shell

Bash là (tính đến ngày nay)các de facto shell on most systems you’ll get in touch with: Linux, macOS, and the WSL on Windows 10.

Cập nhật: macOS kể từ Catalina (mùa thu 2019) sử dụng Zsh

Có những lý do lịch sử khiến Bash trở thành loại shell phổ biến nhất trên thế giới. Trở lại năm 1989, khi nó được phát hành lần đầu tiên, thế giới công nghệ đã rất khác. Vào thời điểm đó, hầu hết phần mềm trong thế giới UNIX đều là mã nguồn đóng. Bản thân Unix đã là mã nguồn đóng và độc quyền.

Để sử dụng hệ thống UNIX, bạn phải sử dụng một trình bao.

Shell phổ biến nhất vào thời điểm đó là mã nguồn đóng và độc quyền, bạn phải trả tiền để sử dụng nó. Đó là vỏ Bourne, có sẵn dưới/bin/shchỉ huy. Nó được gọi là “Bourne” vì người tạo ra nó là Steve Bourne.

Richard Stallman trong những năm đó với Dự án GNU (và sau đó là Linux) đã chuẩn bị cách mạng hóa mọi thứ, bắt đầu cuộc cách mạng Nguồn mở. Dự án GNU cần một trình bao, và với sự trợ giúp của Tổ chức Phần mềm Tự do, Bash đã ra đời. Lấy cảm hứng từ Bourne Shell, Bash có nghĩa làBourne-again shellvà nó là một thành phần chính của Dự án GNU, và có lẽ là một trong những phần mềm thành công nhất của nó mà chúng ta vẫn sử dụng ngày nay.

Bash có thể chạy tất cả các tập lệnh được viết chosh, đây là một tính năng bắt buộc để áp dụng và nó cũng đã giới thiệu nhiều tính năng khác, kể từ những ngày đầu tiên, cung cấp trải nghiệm tốt hơn cho người dùng. Kể từ những ngày đầu tiên đó, Bash đã đạt được rất nhiều cải tiến. Hướng dẫn này mô tả những điều phổ biến và hữu ích nhất mà bạn có thể làm với nó.

Các bước đầu tiên trong Bash

Vì Bash là shell mặc định trong nhiều hệ thống, tất cả những gì bạn cần để bắt đầu bash shell là

  • đăng nhập vào hệ thống, nếu đó là một máy chủ
  • mở thiết bị đầu cuối của bạn, nếu đó là máy tính của bạn

Xem của tôihướng dẫn thiết bị đầu cuối macOSđể biết thêm thông tin về cách sử dụng thiết bị đầu cuối của bạn trên máy Mac.

Ngay sau khi bắt đầu, bạn sẽ thấy một lời nhắc (thường kết thúc bằng$).

Làm thế nào để bạn biết shell đang chạy bash? Hãy thử gõhelpvà nhấn enter.

Xem? Chúng tôi vừa yêu cầu Bash thực hiện lệnhhelpchỉ huy. Lệnh này lần lượt hiển thị cho bạn phiên bản Bash bạn đang chạy và danh sách các lệnh bạn có thể sử dụng.

Cảnh báo: xem phiên bản tôi có ở đó? Đó là 3.2.57. Đây là phiên bản Bash mặc định được cung cấp trong macOS, không bao gồm bản phát hành cao hơn cho các vấn đề cấp phép. Phiên bản Bash này là từ năm 2014. Cài đặt Bash 5.x mới nhất bằng Homebrew, bằng cách gõbrew install bash.

Thường xuyên hơn không, bạn sẽ không bao giờ sử dụng bất kỳ lệnh nào được liệt kê trong trợ giúp bash, trừ khi bạn đang tạotập lệnh shellhoặc những thứ cao cấp.

99% thời gian sử dụng shell hàng ngày là điều hướng qua các thư mục và thực thi các chương trình nhưls,cdvà các tiện ích UNIX dùng chung khác.

Để điều hướng qua hệ thống tệp, bạn sẽ sử dụnglschỉ huy. Nó có sẵn trong/bin/lsvà vì Bash có/binthư mục trong danh sách đường dẫn của nó, bạn chỉ cần nhậplsđể dùng nó.

lsliệt kê các tệp trong thư mục hiện tại. Bạn thường bắt đầu từ thư mục chính của mình, điều này phụ thuộc vào hệ thống nhưng trên macOS thì/Users. Thư mục chính của tôi ở trong/Users/flavio. Điều này không liên quan đến Bash, nó giống một thứ thuộc hệ thống tệp UNIX, nhưng các đối số chồng chéo lên nhau và nếu bạn chưa bao giờ sử dụng shell thì bạn nên biết.

Để điều hướng đến các thư mục khác, bạn sử dụngcd, theo sau là tên của thư mục bạn muốn chuyển đến:

cd Documents

cd ..quay trở lại thư mục mẹ.

Tùy thuộc vào cấu hình Bash của bạn, bạn sẽ thấy thư mục hiện tại của mình được hiển thị trước lời nhắc ($Biểu tượng). Hoặc bạn có thể không, nhưng bạn luôn có thể biết mình đang ở đâu bằng cách nhậppwdvà nhấn enter.

pwdcó nghĩa là * p * tên thể thao của * w * orking * d * irectory

Chỉnh sửa dòng lệnh

Khi bạn đang viết lệnh trong shell, hãy lưu ý rằng bạn có thể di chuyển sang trái và phải bằng các phím mũi tên. Đây là một tính năng của vỏ. Bạn có thể di chuyển xung quanh các lệnh của mình, nhấn nút xóa lùi và sửa các lệnh. Nhấnenterphím thông báo cho trình bao di chuyển và để hệ thống thực hiện lệnh.

Đây là hành vi bình thường và được chấp nhận, nhưng có lẽ điều gì đó đã khiến những người dùng UNIX ban đầu phải “thán phục”.

Các tổ hợp bàn phím cho phép bạn chỉnh sửa nhanh chóng mà không cần chạm vào các phím mũi tên:

  • ctrl+dđể xóa nhân vật hiện được chọn
  • ctrl+fđể đi đến ký tự ở bên phải
  • ctrl+bđể chuyển đến ký tự bên trái

Tự động hoàn thành

Một tính năng hay của Bash khi di chuyển xung quanh hệ thống tệp là tự động hoàn thành. Hãy thử gõcd Docvà nhấntabchìa khóa để làm cho Bash tự động hoàn thànhcd Documents. Nếu có nhiều lựa chọn cho những ký tự đầu tiên đó, Bash sẽ trả lại cho bạn danh sách, vì vậy bạn có thể nhập thêm một vài ký tự để giúp nó loại bỏ sự mơ hồ và nhấntabmột lần nữa để hoàn thành.

Trình bao có thể tự động điền tên tệp, nhưng cũng có thể tên lệnh.

Lệnh shell

Sử dụng shell chúng ta có thể chạy các lệnh có sẵn trên hệ thống. Chúng ta có thể đặt trước các lệnh bằng đường dẫn đầy đủ (ví dụ:/bin/lsđể liệt kê các tệp trong một thư mục) nhưng shell có khái niệmcon đườngvì vậy chúng tôi có thể chỉ cần gõlsvà nó biết nơi tìm thấy hầu hết các lệnh (và chúng ta có thể thêm các thư mục vào đường dẫn này bằng cách cấu hình nó).

Các lệnh chấp nhận đối số. Ví dụls /binsẽ liệt kê tất cả các tệp trong/binthư mục.

Các thông số được bắt đầu bằng dấu gạch ngang-, giốngls -acâu nói nàolsđể hiển thị các tệp ẩn. Các tệp ẩn theo quy ước là các tệp (và thư mục) bắt đầu bằng dấu chấm (.).

Các lệnh shell phổ biến

Có rất nhiều lệnh được cài đặt sẵn trên bất kỳ hệ thống nào và chúng thay đổi đáng kể tùy thuộc vào đó là Linux / macOS hay thậm chí là bản phân phối Linux mà bạn đang chạy.

Tuy nhiên, hãy làm một vòng ngắn gọn về các lệnh shell phổ biến nhất mà bạn có thể chạy. Chúng không được cung cấp bởi shell, mà chúng là các lệnh dòng lệnh mà bạn có thể gọi thông qua shell.

Bất cứ khi nào bạn gặp vấn đề, chẳng hạn như bạn không biết lệnh làm gì, hoặc bạn không biết cách sử dụng nó, hãy sử dụngman. Nó cho phép bạn nhận trợ giúp cho tất cả các lệnh mà tôi sẽ liệt kê và hơn thế nữa. Chạyman lsví dụ.

Đây là các lệnh hệ thống tệp:

  • lsliệt kê các tập tin
  • cdđể thay đổi thư mục
  • rmđể xóa một tệp hoặc thư mục
  • mvđể di chuyển tệp sang thư mục khác hoặc thay đổi tên tệp
  • cpđể sao chép một tập tin
  • pwdđể hiển thị thư mục làm việc hiện tại
  • mkdirđể tạo một thư mục

Mọi tệp trên hệ thống tệp Unix đều có quyền.chmodcho phép bạn thay đổi những điều đó (bây giờ không đi vào nó) vàchowncho phép bạn thay đổi tệpchủ nhân.

cat,tailgreplà hai lệnh siêu hữu ích để làm việc với tệp.

pico,nano,vimemacslà những trình soạn thảo thường được cài đặt.

whereistrên macOS hiển thị vị trí đặt lệnh trên hệ thống.

Tất nhiên còn có nhiều lệnh nữa, nhưng đó là một vài lệnh bạn có thể gặp phải thường xuyên hơn.

Thực thi các lệnh

lscdlà các lệnh, như tôi đã đề cập, được tìm thấy trong/binthư mục. Bạn có thể thực thi bất kỳ tệp nào, miễn đó là tệp thực thi, bằng cách nhập đường dẫn đầy đủ của nó, chẳng hạn/bin/pwd. Các lệnh không cần phải có trong/binthư mục và bạn có thể chạy các tệp thực thi có trong thư mục hiện tại của bạn bằng cách sử dụng./chỉ báo đường dẫn.

Ví dụ, nếu bạn có mộtrunmenộp hồ sơ của bạn/Users/flavio/scriptsthư mục, bạn có thể chạy

cd /Users/flavio/scripts

và sau đó chạy./runmeđể chạy nó.

Hoặc bạn có thể chạy/Users/flavio/scripts/runmetừ Bash, cho dù thư mục hiện tại của bạn ở đâu.

Việc làm

Bất cứ khi nào bạn chạy một lệnh, nếu đó là một chương trình chạy dài, bạn sẽ hoàn toàn sở hữu shell của mình bởi lệnh đó. Bạn có thể hủy lệnh bằng cách sử dụngctrl-C.

Bất cứ lúc nào bạn có thể chạyjobsđể xem các công việc bạn đang thực hiện và trạng thái của chúng.

$ jobs
Job	Group	State	Command
1	72292	stopped	ftp

Another useful command is ps which lists the processes running.

$ ps
  PID TTY           TIME CMD
19808 ttys000    0:00.56 /usr/local/bin/fish -l
65183 ttys001    0:04.34 -fish
72292 ttys001    0:00.01 ftp

top shows the processes and the resources they are consuming on your system.

A job or process can be killed using kill <PID>.

Command history

Pressing the up arrow key will show you the history of the commands you entered. Again, this is a shell feature. Pressing the down arrow key will let you navigate back and forth in time to see what commands you entered previously, and pressing enter will let you run that command again.

This is a quick access to the command history. Running the history command will show you all the commands entered in the shell:

When you start typing a command, Bash can autocomplete it by referencing a previously entered command in the history. Try it by pressing esc followed by tab.

To be honest I find the Fish shell implementation of this to be much better and easier

Setting your default shell

There are many more shells other than Bash. You have Fish, ZSH, TCSH, and others. Any user on the system can choose its own shell.

You set your default login shell by running the chsh -s chsh -s /bin/bash command. You’ll almost never need to do that, unless it was previously changed, for example with Fish:

chsh -s /usr/local/bin/fish

Customizing Bash

I noted before that you might (or might not) see your current working directory in the Bash prompt. Where is this determined? In the Bash configuration!

There’s a bit of confusion here because Bash uses a different configuration file for different scenarios, and it also reads multiple configuration files.

Let’s give some order to this confusion. First, there’s a big distinction whether Bash is initialized as a login shell or not. By login shell we mean that the system is not running a GUI (Graphical User Interface) and you log in to the system through the shell. That’s the case of servers, for example.

In this case, Bash loads this configuration file:

/etc/profile

and then looks in the user home folder and looks for one of these files, in order, executing the first one it finds:

~/.bash_profile
~/.bash_login
~/.profile

were ~ means your home folder (it’s automatically translated by Bash)

This means that if there’s a .bash_profile, ~/.bash_login and ~/.profile are never run, unless explicitly executed in .bash_profile.

If instead of being a login shell Bash is run like I do with macOS, for example, as a normal application, the configuration files change. Bash loads first /etc/bash.bashrc, then ~/.bashrc.

Environment variables

Sometimes you have programs that use environment variables. Those are values that you can set outside of the program, and alter the execution of the program itself. An API key, for example. Or the name of a file.

You can set an environment variable using the syntax

VARIABLE_NAME=variable_value

The value can contain white spaces, by using quotes

VARIABLE_NAME="variable value"

A bash script can use this value by prepending a dollar sign: $VARIABLE_NAME.

Also other programming languages commands can use environment variables, for example here’s how to read environment variables with Node.js.

The system sets up some environment variables for you, like

  • $HOME your home folder
  • $LOGNAME your user name
  • $SHELL the path to your default shell
  • $PATH the path where the shell looks for commands

You can inspect their value by prepending echo to them:

echo $LOGNAME # flavio
echo $HOME # /Users/flavio

A special environment variable: $PATH

I mentioned the $PATH variable. This is a list of folders where the shell will look into when you type a command. Folders are separated by a colon : and they are written in order - Bash will look into the first, search for the command you asked for, and run it if it finds it. Otherwise if goes to the next folder and so on.

My path is currently:

bash-5.0$ echo $PATH
/usr/local/bin:/usr/bin: /bin:/usr/sbin: /sbin:/usr/local/go/bin

You typically edit this in the ~/.bashrc file by prepending or appending items:

PATH = "$PATH:/Users/flavio/bin"

Aliases

Using aliases we can set up shortcuts for common commands. You can give a quick name to a complex combination of parameters, for example.

You define an alias using the syntax

alias <alias>=<command>

if there’s a space in the command you use quotes:

alias <alias>="<command>"

One alias I commonly add to my system is ll:

alias ll="ls --al"

You normally define aliases in your ~/.bashrc file.

Just be careful with quotes if you have variables in the command: using double quotes the variable is resolved at definition time, using single quotes it’s resolved at invokation time. Those 2 are different:

alias lsthis="ls $PWD"
alias lscurrent='ls $PWD'

$PWD refers to the current folder the shell is into. If you now navigate away to a new folder, lscurrent lists the files in the new folder, lsthis still lists the files in the folder you were when you defined the alias.

Advanced command line features

Wildcards

ls and many other commands can make great use of wildcards. You can list all files starting with image:

ls image*

Or all files ending with image:

ls *image

or all files that contain image inside the name:

ls *image*

Redirecting output and standard error error

By default, commands started in the shell print out both the output and errors back to the shell. This might not be what you want. You can decide to write the output to a file instead.

Actually, to a /different file/, because in Unix even the screen is considered to be a file. In particular,

  • 0 identifies the standard input
  • 1 identifies the standard output
  • 2 identifies the standard error

You can redirect the standard output to a file by appending 1> after a command, followed by a file name.

Using the same technique you can use 2> to redirect the standard error.

There is a shortcut > for 1>, since that is used quite a lot.

Example:

ls 1> list.txt 2> error.txt
ls > list.txt 2> error.txt

Another shortcut, &>, redirects /both/ standard output and standard error to a file.

ls &> output.txt

Another frequent thing is to redirect standard error to standard output using 2>&1.

Running a command in the background

You can tell Bash to run a program in the background without it taking control of the shell, by appending & after it:

top &

top is a command that lists the processes running, ordered by most resource consuming.

The application that would normally get control of the shell, is now started but nothing seems to happen. You can bring it back into focus by typing fg (aka *f*ore*g*round), but now we’re entering in the realm of processes and jobs which is a big topic on its own, but a quick overview:

When a command is running you can use ctrl-Z to pause it and bring it to the background. The shell comes back again in the foreground, and you can now run bg to move resume execution of that previously paused job.

When you are ready to go back to it, run fg to bring back that program in the foreground.

You can see all processes running using ps, and the list shows all the processes pid numbers. Using the paused process pid, you can bring to foreground a specific command, for example fg 72292. Same works for bg.

Queuing commands

You can instruct Bash to run a command right after another ends by separating them with a semicolon:

cd /bin; ls

You can repeat this to queue multiple commands in the same line.

Output redirection

A program can receive input from any file using the < operator, and save to a file the output using the > operator:

echo hello > result.txt
wc < result.txt

wc is a command that counts the words it receives as input.

Pipe

Using pipes, any command output can be used as input for a second command. Use the | operator to combine the two. In this example, wc gets its input from the output of echo hello:

echo hello | wc

Grouping commands

Use && to combine two commands using “and”. If the first command executes without problems, run the second, and so on.

Use || to combine two commands using “or”. If the first command executes without problems the second does not run.

! negates the next logical operation:

$ echo hello && echo test
hello
test
$ echo hello || echo test
hello
$ ! echo hello || echo test
hello
test

You can use parentheses to combine expressions to avoid confusion, and also to change the precedence:

$ ! (echo hello) || (echo test)
hello
test
$ ! (echo hello || echo test)
hello

Programming shells

One of the best features of a shell like Bash is its ability to create programs with it, by basically automating commands execution.

I’m going to write a separate guide on Bash scripting soon, which will be separate from this tutorial because the topic is really more in-depth than what I want to add in this introductory Bash guide.

A quick intro though: a script is a text file that starts with a line that indicates that it’s a shell script (and what shell it requires), followed by a list of commands, one per line. Example:

#!/bin/bash
ls

You can save this as a file myscript and make it executable using chmod +x myscript, and run it using ./myscript (./ means “current folder”).

Shell scripting is outside of the scope of this post, but I want you to know about this. Scripts can have control structures and many other cool things.

This same scripting strategy works for other shells, like Zsh:

#!/bin/zsh
ls

Download my free Linux Commands Handbook


More cli tutorials: