Shell腳本深入教程(1):快速入門

来源:https://www.cnblogs.com/f-ck-need-u/archive/2020/02/08/12275851.html
-Advertisement-
Play Games

Shell腳本基礎入門 Bash註釋 Bash只支持單行註釋,使用 開頭的都被當作註釋語句: 通過Bash的一些特性,可以取巧實現多行註釋: 所以,預設情況下讀寫數據都是終端,例如: 改變文件描述符對應的目標,可以改變數據的流向。比如標準輸入fd=1預設流向是終端設備,若將其改為/tmp/a.log ...


Shell腳本基礎入門

Bash註釋

Bash只支持單行註釋,使用#開頭的都被當作註釋語句:

# 整行註釋
echo hello world # 行章節附註釋

通過Bash的一些特性,可以取巧實現多行註釋:

: '
註釋1
註釋2
'

: <<'EOF'
註釋1
註釋2
EOF

____='
註釋1
註釋2
'

但是,別閑的蛋疼去用取巧的多行註釋,安心用#來註釋。

Bash基本數據類型

Bash中基本數據類型只有字元串類型,連數值類型都沒有(declare -i可強制聲明數值類型)。

比如:

# 都會當作字元串
echo haha
echo 1234

Bash字元串串聯

Bash中字元串的串聯操作,直接將兩段數據連接在一起即可,不需要任何操作符。

例如:

echo "junma""jinlong"
echo 1234 5678

命令基本知識

變數賦值和引用變數

a=3
echo $a

a="www.junmajinlong.com"
echo $a

a='hello world'
echo $a

Shell中可以引用未定義的變數:

echo $xyzdefabc

可以定義空變數:

a=
echo $a

變數替換

變數替換是指在命令開始執行前,Shell會先將變數的值替換到引用變數的位置處。

例如:

a="hello"
echo $a world

在echo命令開始執行前,Shell會取得變數a的值hello,並將它替換到命令行的$a處。於是,在echo命令開始執行時,命令行已經變成:

echo hello world

除了變數替換,Shell還會做其它替換:

  • 命令替換
  • 進程替換
  • 算術運算替換
  • 大括弧擴展
  • 波浪號擴展
  • 路徑擴展

這些擴展和替換,都是Shell在調用命令之前就完成的,這和其它語言解析代碼的方式不一樣。

後面會詳細解釋Shell是如何做命令行解析的,如果不掌握命令行解析,當遇到命令行語法錯誤後很可能會花掉大量無謂的時間去調試命令。而掌握命令行解析後,就會對命令生命周期瞭如執掌,不敢說一次就能寫對所有命令行,但能節省大量調試時間,對寫命令行和寫腳本的能力也會上升一個層次。

命令替換

使用反引號或$()可以執行命令替換。

`cmd`
$(cmd)

命令替換是指先執行cmd,將cmd的輸出結果替換到$()或反引號位置處。

例如:

echo `id root`
echo $(id root)

在echo命令執行前,會先執行id命令,id命令的執行結果:

$ id root
uid=0(root) gid=0(root) groups=0(root)

所以會將結果uid=0(root) gid=0(root) groups=0(root)替換$(id root)。於是,echo命令開始執行時,命令行已經變成了:

echo uid=0(root) gid=0(root) groups=0(root)

算術運算

$[]$(())或let命令可以做算術運算。

let是單獨的命令,不能寫在其它命令行中。

a=3
let a=a+1
echo $a

$[]$(())可以寫在命令行內部,Shell在解析命令行的時候,會對它們做算術運算,然後將運算結果替換到命令行中。

a=33
echo $[a+3]
echo $((a+3))

因為變數替換先於算術替換,所以,使用變數名或引用變數的方式都可以:

a=333
echo $[$a+3]
echo $(($a+3))

退出狀態碼

每個命令執行後都會有對應的進程退出狀態碼,用來表示該進程是否是正常退出。

所以,在命令行中,在Shell腳本中,經常會使用特殊變數$?判斷最近一個前臺命令是否正常退出。

通常情況下,如果$?的值:

  • 為0,表示進程成功執行,即正常退出
  • 非0,表示進程未成功執行,即非正常退出
  • 但非0退出狀態碼並不一定表示錯誤,也可能是正常邏輯的退出

另外,在Shell腳本中,所有條件判斷(比如if語句、while語句)都以0退出狀態碼表示True,以非0退出狀態碼為False。

exit命令

exit命令可用於退出當前Shell進程,比如退出當前Shell終端、退出Shell腳本,等等。

exit [N]

exit可指定退出狀態碼N,如果省略N,則預設退出狀態碼為0,即表示正確退出。

後臺執行命令&

在命令的結尾使用&符號,可以將這個命令放入後臺執行。

命令放入後臺後,會立即回到Shell進程,Shell進程會立即執行下一條命令(如果有)或退出。

使用$!可以獲取最近一個後臺進程的PID。

sleep 20 &
echo $!

使用wait命令可以等待後臺進程(當前Shell進程的子進程)完成:

wait [n1 n2 n3 ...]

不給定任何參數時,會等待所有子進程(即所有後臺進程)完成。

sleep 5 &
wait
echo haha

多命令組合

Shell中有多種組合多個命令的方式。

1.cmd1退出後,執行cmd2

cmd1;cmd2

2.cmd1正確退出(退出狀態碼為0)後,執行cmd2

cmd1 && cmd2

3.cmd1不正確退出後,執行cmd2

cmd1 || cmd2

4.邏輯結合:&&||可以隨意結合

# cmd1正確退出後執行cmd2,cmd2正確退出後執行cmd3
cmd1 && cmd2 && cmd3...

# cmd1正確退出則執行cmd2,cmd1不正確退出會執行cmd3
# cmd1正確退出,但cmd2不正確退出,也會執行cmd3
cmd1 && cmd2 || cmd3

# cmd1正確退出會執行cmd3
# cmd1不正確退出會執行cmd2,cmd2正確退出會執行cmd3
cmd1 || cmd2 && cmd3

5.將多個命令分組:小括弧或大括弧可以組合多個命令

# 小括弧組合的多個命令是在子Shell中執行
# 即會先創建一個新的Shell進程,在執行裡面的命令
(cmd1;cmd2;cmd3)

# 大括弧組合的多個命令是在當前Shell中執行
# 大括弧語法特殊,要求:
#   1.開閉括弧旁邊都有空白,否則語法解析錯誤(解析成大括弧擴展)
#   2.寫在同一行時,每個cmd後都要加分號結尾
#   3.多個命令可分行書寫,不要求分號結尾
{ cmd1;cmd2;cmd3; }
{
  cmd1
  cmd2
  cmd3
}

基本重定向

軟體設計認為,程式應該有一個數據來源、數據出口和報告錯誤的地方。在Linux系統中,每個程式預設都會打開三個文件描述符(file descriptor,fd):

  • fd=0:標準輸入,表示程式預設從哪裡讀取數據
  • fd=1:標準輸出,表示程式預設將數據輸出到哪裡
  • fd=2:標準錯誤,表示程式預設將錯誤信息輸出到哪裡

文件描述符,說白了就是系統為了跟蹤打開的文件而分配給它的一個數字,這個數字和文件有對應關係:從文件描述符讀取數據,即表示從對應的文件中讀取數據,向文件描述符寫數據,即表示向對應文件中寫入數據。

Linux中萬物皆文件,文件描述符也是文件。預設:

  • fd=0的標準輸入是/dev/stdin文件
  • fd=1的標準輸出是/dev/stdout文件
  • fd=2的標準錯誤是/dev/stderr文件

這些文件預設又是各個終端的軟鏈接文件:

$ ls -l /dev/std*
lrwxrwxrwx 1 root root 15 Jan  8 20:26 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Jan  8 20:26 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Jan  8 20:26 /dev/stdout -> /proc/self/fd/1

$ ls -l /proc/self/fd/
lrwx------ 1 root root 64 Jan 16 10:40 0 -> /dev/pts/0
lrwx------ 1 root root 64 Jan 16 10:40 1 -> /dev/pts/0
lrwx------ 1 root root 64 Jan 16 10:40 2 -> /dev/pts/0
lr-x------ 1 root root 64 Jan 16 10:40 3 -> /proc/75220/fd

所以,預設情況下讀寫數據都是終端,例如:

# 數據輸出到終端
$ echo haha
$ cat /etc/fstab

# 從終端讀取數據
$ cat
hello   # 在終端輸入
hello   # 在終端輸出
world   # 在終端輸入
world   # 在終端輸出
^C

改變文件描述符對應的目標,可以改變數據的流向。比如標準輸入fd=1預設流向是終端設備,若將其改為/tmp/a.log,便能讓數據寫入/tmp/a.log文件中而不再是終端設備中。

在Shell中,這種改變文件描述符目標的行為稱為重定向,即重新確定數據的流向。

其實,文件描述符有很多類操作,包括fd的重定向、fd的分配(open,即打開文件)、fd複製(duplicate)、fd的移動(move)、fd的關閉(close)。現在只介紹基礎重定向操作。

Shell中,基礎重定向操作有以下幾種方式:

  • [n]>file:覆蓋式輸出重定向,輸出到fd=n的數據改變流向輸出到file文件中,file不存在則創建,file存在則先清空再寫入數據
    • 省略n時>file,等價於1>file,即標準輸出覆蓋重定向到file文件中
  • [n]>>file:追加式輸出重定向,輸出到fd=n的數據改變流向輸出到file文件的尾部,file不存在則創建,file存在則直接追加在文件尾部
    • 省略n時>>file,等價於1>>file,即標準輸出追加重定向到file文件中
  • [n]<file:輸入重定向,以讀取模式打開file文件並分配fd=n,file不存在則報錯
    • 省略n時<file,等價於0<file,即直接從file中讀數據
    • 通常程式都只從fd=0中讀數據,所以當n不等於0時,需要多做一步操作3<file <&3,看不懂先跳過
  • &>file:這是特殊的重定向方式,表示將標準錯誤和標準輸出都重定向到file文件中,等價於>file 2>&1
  • &>>file:這是特殊的重定向方式,表示將標準錯誤和標準輸出都追加到file文件中,等價於>>file 2>&1

另外,經常用於輸出的一個特殊目標文件是/dev/null,它是空設備,可以直接丟掉所有寫入它的數據。

echo www.junmajinlong.com >/dev/null
curl -I www.junmajinlong.com 2>/dev/null >/tmp/a.log

cat </etc/fstab

一個經常用的技巧是清空文件的方式:

$ cat /dev/null >file
$ >file

區分cat <file和cat file

cat是一個命令,這個命令的源代碼中寫了一些代碼用來處理選項和參數。

cat -n /etc/fstab

cat命令開始執行後,會識別-n選項,該選項會讓cat輸出時同時輸出行號,cat同時還會識別/etc/fstab參數,cat會讀取參數指定的文件然後輸出。

如果沒有指定cat的文件參數,則cat預設會從標準輸入中讀取數據。預設的標準輸入是終端,所以在沒有改變標準輸入的流向時,會從終端讀取數據,也就是用戶輸入什麼字元,就讀取什麼字元,然後輸出什麼字元:

$ cat
junmajinlong   # 在終端輸入
junmajinlong   # 在終端輸出
junma   # 在終端輸入
junma   # 在終端輸出
^C

但用戶可以改變標準輸入的來源。比如:

$ cat </etc/fstab

表示將標準輸入來源改為/etc/fstab文件,於是cat會從/etc/fstab中讀取數據。

另外,約定俗成的,會使用一個-來表示標準輸入或標準輸出。

# 下麵是等價的,都表示從標準輸入中讀取數據
cat -
cat /dev/stdin
cat

註:這並非是一貫正確的,只是約定俗成的大多數程式的代碼中都定義了-相關的代碼處理。可參考相關命令的man手冊。如man cat中有一行:

With no FILE, or when FILE is -, read standard input.

here doc

輸入重定向是<,除此之外還有<<、<<<

<<符號表示here doc。也就是說,它後面跟的是一篇文檔,就像一個文件一樣,只不過這個文件的內容是臨時定義在<<符號後的。here doc常用於指定多行數據輸入。

既然是文檔,就有文檔起始符號表示文檔從此開始和文檔終止符號表示文檔到此結束。起始符和終止符中間的內容全部是文檔內容。文檔內容會作為標準輸入的數據被讀取。

文檔的起始符和終止符可以隨意定義,但兩者前後必須一樣。常見的符號是:

  • EOF:end of file
  • EOL:end of line
  • EOB:end of block

例如:

# here doc作為標準輸入被讀取,然後被cat輸出
cat <<EOF
hello
world
EOF

# here doc的內容還會被cat覆蓋式輸出到指定文件
cat <<eof >/tmp/file
hello
world
eof

# here doc的內容還會被cat追加式輸出到指定文件
cat <<eof >>/tmp/file
hello
world
eof

# here doc和重定向符號的前後位置隨意
cat >>/tmp/file<<eof
...
eof

另外,如果將起始符用引號包圍,則不會進行變數替換、命令替換、算術替換等。如果不用引號包圍起始符,則會進行替換。

a=333
cat <<eof
$a
eof

cat <<"eof"
$a
eof

輸出結果:

333
$a

here string

<<<表示here string。也就是說該符號後面是一個字元串,這個字元串會作為標準輸入的內容。

cat <<<"www.junmajinlong.com"

使用單引號包圍here string時,不會進行變數替換、命令替換等,使用雙引號包圍時會進行替換。

$ a=3333
$ cat <<<$a            
3333
$ cat <<<"hello world$a"
hello world3333
$ cat <<<'hello world$a' 
hello world$a

here string常可以替代管道前的echo命令echo xxx|。例如:

# 下麵是等價的
echo hello world | grep "llo"
grep "llo" <<<"hello world"

管道

管道的用法:

cmd1 | cmd2 | cmd3...

每個豎線代表一個管道。上面命令行表示cmd1的標準輸出會放進管道,cmd2會從管道中讀取進行處理,cmd2的標準輸出會放入另一個管道,cmd3會從這個管道中讀取數據進行處理。後面還可以接任意數量的管道。

Shell管道是Shell中最值得稱贊的功能之一,它以非常簡潔的形式實現了管道的進程間通信方式,我個人認為Shell處理文本數據的半壁江山都來自於豎線形式的管道。像其它編程語言,打開管道後還要區分哪個進程寫管道、哪個進程讀管道,為了安全,每個進程還要關閉不用的讀端或寫端,總之就是麻煩,而Shell的管道非常簡潔,豎線左邊的就是寫管道的,豎線右邊的就是讀管道的。

例如:

ps aux | grep 'sshd'

ps命令產生的數據(標準輸出)會寫進管道,只要管道內一有數據,grep命令就從中讀取數據進行處理。

那下麵的命令中,grep從哪讀數據呢?

ps aux | grep '#' /etc/fstab

那想要讓grep既從/etc/fstab讀取數據,也從管道中讀取數據呢?

ps aux | grep '#' /etc/fstab /etc/stdin
ps aux | grep '#' /etc/fstab -

tee命令

tee命令可將一份標準輸入原樣拷貝到標準輸出和0或多個文件中。換句話說,tee的作用是數據多重定向。

NAME
    tee - read from standard input and write to standard output and files

SYNOPSIS
    tee [OPTION]... [FILE]...

DESCRIPTION
    Copy standard input to each FILE, and also to standard output.

    -a, --append
        ppend to the given FILEs, do not overwrite

如圖:

1581130562081

例如:

$ echo hello world | tee /tmp/file1 /tmp/file2 | cat
$ echo hello world | tee -a /tmp/file3 >/dev/null

進程替換

Bash還支持進程替換(註:有些Shell不支持進程替換)。

進程替換的語法:

<(cmd)
>(cmd)

進程替換和命令替換類似,都是讓cmd命令先執行,因為它們都是在Shell解析命令行的階段執行的。

進程替換先讓cmd放入後臺非同步執行,並且不會等待cmd執行完。

其實,每個進程替換都是一個虛擬文件,只不過這個文件的內容是由cmd命令產生的(<(cmd))或被cmd命令讀取的(>(cmd))。

$ echo <(echo www.junmajinlong.com)
/dev/fd/63

既然進程替換是文件,那麼它就可以像文件一樣被操作。比如被讀取、被當作標準輸入重定向的數據源等等:

# cmd做數據產生者
$ cat <(echo www.junmajinlong.com)   # 等價於cat /dev/fd/63
$ cat < <(echo www.junmajinlong.com) # 等價於cat </dev/fd/63

# cmd做數據接收者
$ echo hello world > >(grep 'llo')
$ echo hello world | tee >(grep 'llo') >(grep 'rld') >/dev/null

條件測試語句

test命令或功能等價的Bash內置命令[ ]可以做條件測試,如果測試的結果為True,則退出狀態碼為0。

此外,還可以使用[[]]來做條件測試,甚至let、$[]、$(())也可以做條件測試,但這裡暫不介紹。

這些條件測試常用在if、while語句中,也常用在cmd1 && cmd2 || cmd3格式的命令行中。

用法示例:

sh_file=test.sh
[ -x "$sh_file" ] && ./$sh_file || { echo "can't execute,exit...";exit 1; }
test -x "$sh_file" && ./$sh_file || { echo "can't execute,exit...";exit 1; }

[]中的條件測試需要和開閉中括弧使用空格隔開,否則語法解析錯誤。

無測試內容

[  ]
test

沒有任何測試內容時,直接返回false。

true和false命令

true命令直接返回true,即退出狀態碼為0。

false命令直接返回false,即退出狀態碼非0。

$ true
$ echo $?  # 0
$ false
$ echo $?  # 1

文件類測試

條件表達式 含義
-e file 文件是否存在(exist)
-f file 文件是否存在且為普通文件(file)
-d file 文件是否存在且為目錄(directory)
-b file 文件是否存在且為塊設備block device
-c file 文件是否存在且為字元設備character device
-S file 文件是否存在且為套接字文件Socket
-p file 文件是否存在且為命名管道文件FIFO(pipe)
-L file 文件是否存在且是一個鏈接文件(Link)

文件屬性類測試

條件表達式 含義
-r file 文件是否存在且當前用戶可讀
-w file 文件是否存在且當前用戶可寫
-x file 文件是否存在且當前用戶可執行
-s file 文件是否存在且大小大於0位元組,即檢測文件是否非空文件
-N file 文件是否存在,且自上次read後是否被modify

兩文件之間的比較

條件表達式 含義
file1 -nt file2 (newer than)判斷file1是否比file2新
file1 -ot file2 (older than)判斷file1是否比file2舊
file1 -ef file2 (equal file)判斷file1與file2是否為同一文件

數值大小比較

條件表達式 含義
int1 -eq int2 兩數值相等(equal)
int1 -ne int2 兩數值不等(not equal)
int1 -gt int2 n1大於n2(greater than)
int1 -lt int2 n1小於n2(less than)
int1 -ge int2 n1大於等於n2(greater than or equal)
int1 -le int2 n1小於等於n2(less than or equal)

字元串比較

條件表達式 含義
-z str (zero)判定字元串是否為空?str為空串,則true
str
-n str
判定字元串是否非空?str為串,則false。註:-n可省略
str1 = str2
str1 == str2
str1和str2是否相同,相同則返回true。"=="和"="等價
str1 != str2 str1是否不等於str2,若不等,則返回true
str1 > str2 str1字母順序是否大於str2,若大於則返回true
str1 < str2 str1字母順序是否小於str2,若小於則返回true

邏輯運算符

條件表達式 含義
-a或&& (and)兩表達式同時為true時才為true。
"-a"只能在test或[]中使用,&&只能在[[]]中使用
-o或|| (or)兩表達式任何一個true則為true。
"-o"只能在test或[]中使用,||只能在[[]]中使用
! 對錶達式取反
( ) 改變表達式的優先順序,為了防止被shell解析,應加上反斜線轉義( )

if語句

if test-commands; then
  consequent-commands;
[elif more-test-commands; then
  more-consequents;]
[else alternate-consequents;]
fi

test-commands既可以是test測試或[]、[[]]測試,也可以是任何其它命令,test-commands用於條件測試,它只判斷命令的退出狀態碼是否為0,為0則為true。

例如:

if [ "$a" ];then echo '$a' is not none;else echo '$a' undefined or empty;fi

if [ ! -d ~/.ssh ];then
  mkdir ~/.ssh
  chown -R $USER.$USER ~/.ssh
  chmod 700 ~/.ssh
fi

if grep 'junmajinlong' /etc/passwd &>/dev/null;then
  echo 'User "junmajinlong" already exists...'
elif grep 'malongshuai' /etc/passwd &>/dev/null;then
  echo 'User "malongshuai" already exists...'
else
  echo 'you should create user,exit...'
  exit 1
fi

case

case常用於確定的分支判斷。比如:

while [ ${#@} -gt 0 ];do
  case "$1" in
    start)
        echo start;;
    stop)
        echo stop
        ;;
    restart)
        echo restart
        ;;
    reload | force-reload)
        echo reload;;
    status)
        echo status;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|reload|force-reload}"
        exit 2
  esac
done

case用法基本要求:

  • 除最後一個分支外,每個分支都以;;結尾,否則出現分支穿透(所以;;不是必須的)
  • 分支條件可以使用通配符號
  • 分支條件中可使用豎線隔開多個條件,表示只要匹配其中之一就執行該分支
  • 最後一般會定義一個能匹配其它任意條件的預設分支,即*)

下麵是為ping命令自定義設計選項的腳本:

#!/bin/bash
while [ $1 ];do
  case "$1" in 
    -c|--count)
      count=$2
      shift 2
      ;;
    -t|--timeout)
      timeout=$2
      shift 2
      ;;
    -h|--host)
      host=$2
      shift 2
      ;;
    *)
      echo "wrong options or arguments"
      exit 1
  esac
done

ping -c $count -W timeout $host

執行:

$ chmod +x ping.sh
$ ./ping.sh -c 5 -t 2 -h www.baidu.com

for迴圈

有兩種for迴圈結構:

# 成員測試類語法
for i in word1 word2 ...;do cmd_list;done

# C語言for語法
for (( expr1;expr2;expr3 ));do cmd_list;done

成員測試類的for迴圈中,in關鍵字後是使用空格分隔的一個或多個元素,for迴圈時,每次從in關鍵字後面取一個元素並賦值給i變數。

例如:

$ for i in 1 2 3 4;do echo $i;done
1
2
3
4
$ for i in 1 2 "3 4";do echo $i;done
1
2
3 4

C語言型的for語法中,expr1是初始化語句,expr2是迴圈終點條件判斷語句,expr3是每輪迴圈後執行的語句,一般用來更改條件判斷相關的變數。

for ((i=1;i<=3;++i));do echo $i;done
1
2
3

while迴圈

while test_cmd_list;do cmd_list;done

while迴圈,開始時會測試test_cmd_list,如果測試的退出狀態碼為0,則執行一次迴圈體語句cmd_list,然後再測試test_cmd_list,一直迴圈,直到測試退出狀態碼非0,迴圈退出。

例如:

let i=1,sum=0;
while [ $i -le 10 ];do 
  let sum=sum+i
  let ++i
done

還有until迴圈語句,但在Shell中用的很少。

while迴圈經常會和read命令一起使用,read是Bash的內置命令,可用來讀取文件,通常會按行讀取:每次讀一行。

例如:

cat /etc/fstab | while read line;do
  let num+=1
  echo $num: $line
done

上面的命令行中,首先cat進程和while結構開始運行,while結構中的read命令從標準輸入中讀取,也就是從管道中讀取數據,每次讀取一行,因為管道中最初沒有數據,所以read命令被阻塞處於數據等待狀態。當cat命令讀完文件所有數據後,將數據放入到管道中,於是read命令從管道中每次讀取一行並將所讀行賦值給變數line,然後執行迴圈體,然後繼續迴圈,直到read讀完所有數據,迴圈退出。

但註意,管道兩邊的命令預設是在子Shell中執行的,所以其設置的變數在命令執行完成後就消失。換句話說,在父Shell中無法訪問這些變數。比如上面的num變數是在管道的while結構中設置的,除了在while中能訪問該變數,其它任何地方都無法訪問它。

如果想要訪問while中賦值的變數,就不能使用管道。如果是直接從文件讀取,可使用輸入重定向,如果是讀取命令產生的數據,可使用進程替換。

while read line;do
  let num1+=1
  echo $num1: $line
done </etc/fstab
echo $num1

while read line;do
  let num2+=1
  echo $num2: $line
done < <(grep 'UUID' /etc/fstab)

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 之前終於在Linux上部署好了.NetCore站點,但是這個站點非常“脆弱”。當我的ssh連接關閉或者我想在當前連接執行其他命令時候就必須關閉dotnet站點的執行程式。這顯然不是我想要達到的效果,還好知道有所謂的守護進程這個東西,大多數人都是推薦採取Supervisor來進行Linux上的應 ...
  • 首先我們先來說說這個ONNX ONNX是一種針對機器學習所設計的開放式的文件格式,用於存儲訓練好的模型。它使得不同的人工智慧框架(如Pytorch, MXNet)可以採用相同格式存儲模型數據並交互。 ONNX的規範及代碼主要由微軟,亞馬遜 ,Facebook 和 IBM 等公司共同開發,以開放源代碼 ...
  • 前言 最近的新型冠狀病毒流行讓很多人主動在家隔離,希望疫情能快點消退。武漢加油,中國必勝! Asp.Net Core 提供了內置的網站國際化(全球化與本地化)支持,微軟還內置了基於 resx 資源字元串的國際化服務組件。可以在入門教程中找到相關內容。 但是內置實現方式有一個明顯缺陷,resx 資源是 ...
  • 一、前言 在平時的開發中,當用戶修改數據時,一直沒有很好的辦法來記錄具體修改了那些信息,只能暫時採用將類序列化成 json 字元串,然後全塞入到日誌中的方式,此時如果我們想要知道用戶具體改變了哪幾個欄位的值的話就很困難了。因此,趁著這個假期,就來解決這個一直遺留的小問題,本篇文章記錄了我目前實現的方 ...
  • 很久沒有寫過 .NET Core 相關的文章了,目前關店在家休息所以有些時間寫一篇新的
  • 首先,先看我個人的項目結構。 這個webapi項目是專門作為圖片上傳的業務處理,而其中分為兩個控制器:單圖片上傳和多圖片上傳。在接下來的內容主要還是針對單文件上傳,對於多文件的上傳,我暫且尚未研究成功。 其中pictureoptions類,由於我把關於圖片上傳相關的配置項(保存路徑、限制的文件類型和 ...
  • 編譯安裝 Centos8下PHP源碼編譯和通過yum安裝的區別和以後的選擇 其實這兩種方法各有千秋: yum安裝: 從yum安裝來說吧,yum相當於是自動化幫你安裝,你不用管軟體的依賴關係,在yum安裝過程是幫你把軟體的全部依賴關係幫你傻瓜式的解決了。而且現在Centos7的服務啟動已經換成syst ...
  • 這裡分享嵌入式領域有用有趣的項目/工具以及一些熱點新聞,農曆年分二十四節氣,希望在每個交節之日準時發佈一期 ...
一周排行
    -Advertisement-
    Play Games
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...