Golang文件流下载,边下载边计算MD5

当时是为了测试文件网卡问题,发现同样的文件,在一个很烂的网卡中不断的下载,计算的文件MD5会不一样的问题。代码记录下,留作参考。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package main

import (
"crypto/md5"
"encoding/hex"
"flag"
"fmt"
"io"
"net/http"
"os"
"strconv"
"time"
)

var (
url = "被下载文件链接"
data = make(map[string]int)
logFile = flag.String("logFile", os.Getenv("HOME")+"/"+"network-card-test.log", "日志文件路径") // /Users/xxx/Downloads/fuck.log
)

func main() {
flag.Parse()
for {
handle()
}
}

func handle() {
md5Str, err := download(url)
if err != nil {
log(err.Error())
return
}

defer func() {
count := data[md5Str]
data[md5Str] = count + 1
}()

count, found := data[md5Str]
if !found && len(data) > 0 {
log("文件MD5异常:" + md5Str + ", count=" + strconv.Itoa(count))
} else {
log("文件MD5:" + md5Str + ", count=" + strconv.Itoa(count))
}
}

func download(url string) (string, error) {
var (
err error
resp *http.Response
contentLen int64
downloadLen int
)
if resp, err = http.Get(url); err != nil {
return "", err
}

if contentLen, err = strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 64); err != nil {
return "", err
}

defer func() {
_ = resp.Body.Close()
fmt.Print("\n")
}()

h := md5.New()
for {
buf := make([]byte, 1024)
c, e := resp.Body.Read(buf)
if e != nil && e != io.EOF {
return "", e
}
downloadLen += c

printProgress(downloadLen, contentLen)

h.Write(buf[0:c])

if e != nil && e == io.EOF {
break
}
}
return hex.EncodeToString(h.Sum(nil)), nil
}

func printProgress(downloadLen int, contentLen int64) {
fmt.Printf("\r")
fmt.Printf("Downloading... %d of %d", downloadLen, contentLen)
}

func log(content string) {
content = time.Now().Format("2006-01-02 15:04:05") + ": " + content

fmt.Println(content)

file, err := os.OpenFile(*logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
fmt.Println(err.Error())
return
}
defer func() {
_ = file.Close()
}()

_, err = file.WriteString(content + "\n")
if err != nil {
fmt.Println(err.Error())
}
}

Go语言http请求计算文件md5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package main

import (
"crypto/md5"
"encoding/hex"
"fmt"
"io"
"net/http"
"strconv"
)

func main() {
ret, err := download("http://....")
if err != nil {
fmt.Println(err)
}
fmt.Println(ret)
}

func download(url string) (string, error) {
var (
err error
resp *http.Response
contentLen int64
downloadLen int
)
if resp, err = http.Get(url); err != nil {
return "", err
}

if contentLen, err = strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 64); err != nil {
return "", err
}

defer func() {
_ = resp.Body.Close()
fmt.Print("\n")
}()

h := md5.New()
for {
buf := make([]byte, 1024)
c, e := resp.Body.Read(buf)
if e != nil && e != io.EOF {
return "", e
}
downloadLen += c

printProgress(downloadLen, contentLen)

h.Write(buf[0:c])

if e != nil && e == io.EOF {
break
}
}
return hex.EncodeToString(h.Sum(nil)), nil
}

func printProgress(downloadLen int, contentLen int64) {
fmt.Printf("\r")
fmt.Printf("Downloading... %d of %d", downloadLen, contentLen)
}

使用PM2运行springboot项目

新建文件:pm2.json

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"name": "test",
"script": "java",
"args": [
"-jar",
"/home/test/test.jar",
"--spring.profiles.active=prod"
],
"exec_interpreter": "",
"exec_mode": "fork",
"error_file" : "/data/logs/error.log",
"out_file" : "/data/logs/out.log"
}

然后执行命令:pm2 start pm2.json启动服务。

解决nvm导致terminal打开慢的问题

电脑上是使用nvm安装的node,安装之后每次打开一个新的terminal都比较慢,运营是因为termainl在打开的时候会加载nvm相关内容,如下:

1
2
3
4
# nvm
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion

可以按照下面方式来修改,只有在需要用到nvm的时候才去加载:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# nvm
export NVM_DIR="$HOME/.nvm"
#[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
#[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
function _install_nvm() {
unset -f nvm
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This sets up nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # load nvm bash_completion
nvm "$@"
}

function nvm() {
_install_nvm "$@"
}

同时安装多个版本JDK,快速切换JDK版本

推荐一个工具:https://github.com/jenv/jenv

1. Getting Started

Follow the steps below to get a working jenv installation with knowledge of your java environment. Read all the code you execute carefully: a $ symbol at the beginning of a line should be omitted, since it’s meant to show you entering a command into your terminal and observing the response after the command.

1.1 Installing jenv

On OSX, the simpler way to install jEnv is using Homebrew

position-relative
1
brew install jenv

Alternatively, and on Linux, you can install it from source :

position-relative
1
2
3
4
5
6
7
git clone https://github.com/jenv/jenv.git ~/.jenv
# Shell: bash
echo 'export PATH="$HOME/.jenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(jenv init -)"' >> ~/.bash_profile
# Shell: zsh
echo 'export PATH="$HOME/.jenv/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(jenv init -)"' >> ~/.zshrc

Restart your shell by closing and reopening your terminal window or running exec $SHELL -l in the current session for the changes to take effect.

To verify jenv was installed, run jenv doctor. On a macOS machine, you’ll observe the following output:

position-relative
1
2
3
4
5
6
$ jenv doctor
[OK] No JAVA_HOME set
[ERROR] Java binary in path is not in the jenv shims.
[ERROR] Please check your path, or try using /path/to/java/home is not a valid path to java installation.
PATH : /Users/user/.jenv/libexec:/Users/user/.jenv/shims:/Users/user/.jenv/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
[OK] Jenv is correctly loaded

Observe that jenv is correctly loaded but Java is not yet installed.

To make sure JAVA_HOME is set, make sure to enable the export plugin:

position-relative
1
2
jenv enable-plugin export
exec $SHELL -l

Problem? Please visit the Trouble Shooting Wiki page.

Continue to the next section to install java.

Untested: While this fork has improved fish shell support, it has not been tested by this maintainer. To install jenv for Fish according to the contributor’s instructions:

position-relative
1
2
3
4
echo 'set PATH $HOME/.jenv/bin $PATH' >> ~/.config/fish/config.fish
echo 'status --is-interactive; and source (jenv init -|psub)' >> ~/.config/fish/config.fish
cp ~/.jenv/fish/jenv.fish ~/.config/fish/functions/jenv.fish
cp ~/.jenv/fish/export.fish ~/.config/fish/functions/export.fish

1.2 Adding Your Java Environment

Use jenv add to inform jenv where your Java environment is located. jenv does not, by itself, install Java.

For example, on macOS, use brew to install the latest Java (OpenJDK 11) followed by the appropriate jenv add PATH_TO_JVM_HOME command to recognize it.

position-relative
1
2
brew install --cask java
jenv add $(/usr/libexec/java_home)

With macOS OpenJDK 11.0.2 installed, for example, either of these commands will add /Library/Java/JavaVirtualMachines/openjdk-11.0.2.jdk/Contents/Home as a valid JVM. Your JVM directory may vary!

Observe now that this version of Java is added to your java versions command:

position-relative
1
2
3
4
5
$ jenv versions
* system (set by /Users/user/.jenv/version)
11.0
11.0.2
openjdk64-11.0.2

By default, the latest version of Java is your system Java on macOS.

We’ll now set a jenv local VERSION local Java version for the current working directory. This will create a .java-version file we can check into Git for our projects, and jenv will load it correctly when a shell is started from this directory.

position-relative
1
2
3
4
$ jenv local 11.0.2
$ exec $SHELL -l
$ cat .java-version
11.0.2

Is JAVA_HOME set?

position-relative
1
2
$ echo ${JAVA_HOME}
/Users/bberman/.jenv/versions/11.0.2

Yes! Observe that JAVA_HOME is set to a valid shim directory. Unlike the main repository’s documentation we helpfully installed the export plugin, and we now have the most important jenv features covered.

If you executed this commands inside your $HOME directory, you can now delete .java-version:

position-relative
1
rm .java-version

1.3 Setting a Global Java Version

Use jenv global VERSION to set a global Java version:

position-relative
1
jenv global 11.0.2

When you next open a shell or terminal window, this version of Java will be the default.

On macOS, this sets JAVA_HOME for GUI applications on macOS using jenv macos-javahome. Integrates this tutorial to create a file that does not update dynamically depending on what local or shell version of Java is set, only global.

1.4 Setting a Shell Java Version

Use jenv shell VERSION to set the Java used in this particular shell session:

position-relative
1
jenv shell 11.0.2

2 Common Workflows

These common workflows demonstrate how to use jenv to solve common problems.

2.1 Using Two JVMs on macOS

Our goal is to have both the latest version of Java and JDK 8 installed at the same time. This is helpful for developing Android applications, whose build tools are sensitive to using an exact Java version.

We’ll resume where we left off with Java 11.0.2 installed. Let’s install Java 8 now:

position-relative
1
2
brew install --cask adoptopenjdk8
brew install --cask caskroom/versions/adoptopenjdk8

This will install the latest version of Java 8 to a special directory in macOS. Let’s see which directory that is:

position-relative
1
2
3
$ ls -1 /Library/Java/JavaVirtualMachines 
adoptopenjdk-8.jdk
openjdk-11.0.2.jdk

Observe the adoptopenjdk-8.jdk directory. Your exact version may vary. We cannot retrieve this using /usr/libexec/java_home, unfortunately. We’ll add the Java home directory using jenv so that it shows up in our jenv versions command:

position-relative
1
2
3
4
5
6
7
8
9
10
11
12
13
$ jenv add /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/
openjdk64-1.8.0.222 added
1.8.0.222 added
1.8 added
$ jenv versions
* system
1.8
1.8.0.222
openjdk64-1.8.0.222
11.0
11.0.2
openjdk64-11.0.2
oracle64-1.8.0.202-ea

批量拉取代码

场景:目录中有多个git项目,想要更新批量拉取一下这些项目的最新代码。

实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/sh
for dir in $(ls -d */); do
cd $dir
if [ -d ".git" ]; then
branch=$(git symbolic-ref --short -q HEAD)
if [ "$branch" != "master" ]; then
echo "skip $dir branch: $branch"
else
echo "dir:$dir branch: $branch"
git pull origin $branch
fi
fi
cd ..
done

扫码目录下的所有项目,如果发现当前项目在master分支,那么pull一下代码。

MacOS安装PHP

偶然的机会需要用一下PHP,记录下安装方式。本身mac系统是自带php的,但是自带的修改起来及其不方便,不好安装扩展。所以直接使用brew安装。

brew安装php

1
2
3
4
brew search php  使用此命令搜索可用的PHP版本
brew install php@7.3.21 使用此命令安装指定版本的php
brew install brew-php-switcher 安装php多版本切换工具
brew-php-switcher 7.3.21 切换PHP版本到7.3.21(需要brew安装多个版本)

安装PHP扩展

1
2
3
4
5
pecl version 查看版本信息
pecl help 可以查看命令帮助
pecl search redis 搜索可以安装的扩展信息
pecl install redis 安装扩展
pecl install http://pecl.php.net/get/redis-4.2.0.tgz 安装指定版本扩展

群辉QNAP使用备忘

记录家里的群辉NAS使用备忘,防止忘记了。

IP

192.168.1.13

文件目录

实际文件目录在:/share/…

备忘

很多图片传重复了,抽空写个脚本判断下是否是重复文件,如果是重复的只保留一份就够了,节省磁盘空间,就判断文件的md5即可。

mac iterm2 rz与sz的功能

本文主要介绍mac环境下使用iterm2rz sz功能的安装流程。

1. 安装lrzsz

1
brew install lrzsz

2. 安装执行脚本

iterm2-send-zmodem.shiterm2-recv-zmodem.sh保存到/usr/local/bin目录下。

iterm2-send-zmodem.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/bin/bash
# Author: Matt Mastracci (matthew@mastracci.com)
# AppleScript from http://stackoverflow.com/questions/4309087/cancel-button-on-osascript-in-a-bash-script
# licensed under cc-wiki with attribution required
# Remainder of script public domain

osascript -e 'tell application "iTerm2" to version' > /dev/null 2>&1 && NAME=iTerm2 || NAME=iTerm
if [[ $NAME = "iTerm" ]]; then
FILE=$(osascript -e 'tell application "iTerm" to activate' -e 'tell application "iTerm" to set thefile to choose file with prompt "Choose a file to send"' -e "do shell script (\"echo \"&(quoted form of POSIX path of thefile as Unicode text)&\"\")")
else
FILE=$(osascript -e 'tell application "iTerm2" to activate' -e 'tell application "iTerm2" to set thefile to choose file with prompt "Choose a file to send"' -e "do shell script (\"echo \"&(quoted form of POSIX path of thefile as Unicode text)&\"\")")
fi
if [[ $FILE = "" ]]; then
echo Cancelled.
# Send ZModem cancel
echo -e \\x18\\x18\\x18\\x18\\x18
sleep 1
echo
echo \# Cancelled transfer
else
/usr/local/bin/sz "$FILE" --escape --binary --bufsize 4096
sleep 1
echo
echo \# Received "$FILE"
fi

iterm2-recv-zmodem.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/bash
# Author: Matt Mastracci (matthew@mastracci.com)
# AppleScript from http://stackoverflow.com/questions/4309087/cancel-button-on-osascript-in-a-bash-script
# licensed under cc-wiki with attribution required
# Remainder of script public domain

osascript -e 'tell application "iTerm2" to version' > /dev/null 2>&1 && NAME=iTerm2 || NAME=iTerm
if [[ $NAME = "iTerm" ]]; then
FILE=$(osascript -e 'tell application "iTerm" to activate' -e 'tell application "iTerm" to set thefile to choose folder with prompt "Choose a folder to place received files in"' -e "do shell script (\"echo \"&(quoted form of POSIX path of thefile as Unicode text)&\"\")")
else
FILE=$(osascript -e 'tell application "iTerm2" to activate' -e 'tell application "iTerm2" to set thefile to choose folder with prompt "Choose a folder to place received files in"' -e "do shell script (\"echo \"&(quoted form of POSIX path of thefile as Unicode text)&\"\")")
fi

if [[ $FILE = "" ]]; then
echo Cancelled.
# Send ZModem cancel
echo -e \\x18\\x18\\x18\\x18\\x18
sleep 1
echo
echo \# Cancelled transfer
else
cd "$FILE"
/usr/local/bin/rz --rename --escape --binary --bufsize 4096
sleep 1
echo
echo
echo \# Sent \-\> $FILE
fi

3. 赋予这两个文件可执行权限

1
chmod 777 /usr/local/bin/iterm2-*

4. 设置Iterm2的Tirgger特性

设置Iterm2的Tirgger特性,profiles->default->editProfiles->Advanced中的Tirgger

添加两条trigger,分别设置 Regular expression,Action,Parameters,Instant如下:

1
2
3
4
5
6
7
8
9
Regular expression: rz waiting to receive.\*\*B0100
Action: Run Silent Coprocess
Parameters: /usr/local/bin/iterm2-send-zmodem.sh
Instant: checked

Regular expression: \*\*B00000000000000
Action: Run Silent Coprocess
Parameters: /usr/local/bin/iterm2-recv-zmodem.sh
Instant: checked

示例图:

5. 使用

  • 上传文件:rz
  • 下载文件:sz + file

参考: