H5+app,自動更新后自動刪除安裝包,H5+app — 自動更新

H5+app 自動刪除安裝包

一、前言

  之前做好的app自動更新,遺留下了一個問題,就是自動更新后安裝包沒有自行刪除掉。

  好像現在的手機的系統是有安裝完自動清理安裝包的。想我這個H5+的app安裝完后是沒有自動刪除的,所以就需要用代碼去刪除掉。

二、解決方式

  使用html5+plus,提供的IO模塊來操作自動更新后遺留下來的apk文件。

  參考文檔:

    http://www.html5plus.org/doc/zh_cn/io.html

  IO模塊:管理本地文件系統,用於對文件系統的目錄瀏覽、文件的讀取、文件的寫入等操作。通過plus.io可獲取文件系統管理對象。

  原理:1、通過plus.io.requestFileSystem請求本地文件系統對象

           第一個參數類型是  PUBLIC_DOWNLOADS: 程序公用下載目錄常量

        成功返回后的參數fs,即:該下載目錄下的所有文件,然後進行遍歷

        2、通過plus.io.resolveLocalFileSystemURL操作文件

        第一個參數即文件的路徑名,成功返回后的參數entry,即:文件對象

        得到文件的對象就可以進行操作,查看文件名,文件大小,刪除,複製文件等操作

三、代碼

  1、下面即為代碼的實現

                plus.io.requestFileSystem(plus.io.PUBLIC_DOWNLOADS, function(fs) {
                                // fs.root是根目錄操作對象DirectoryEntry
                                var directoryReader = fs.root.createReader();
                                directoryReader.readEntries(function(entries) {
                                    for (var i = 0; i < entries.length; i++) {
                                        var fileName = entries[i].name;  var filePath = "_downloads/" + entries[i].name;
                                        plus.io.resolveLocalFileSystemURL(filePath, function(entry) {
                                            // 可通過entry對象操作test.html文件 
                                            // entry.file(function(file) {
                                            //     console.log(file.name);
                                            // });
                                            entry.remove();
                                        }, function(e) {
                                            // console.log("Resolve file URL failed: " + e.message);
                                        });
                                    }
                                }, function(e) {
                                    // alert("Read entries failed: " + e.message);
                                });
                            });

  2、其他做法

     現在有個問題,就是安裝的后重啟是不可控,所以我最簡單的做法就是保留最新版本的apk,其他版本都刪除

     當然可以有其他做法,就是檢測是否需要更新,如果不需要更新,則啟動刪除程序,將本地安裝清除。

function autoDeleteApk() {
                plus.runtime.getProperty(plus.runtime.appid, function(inf) {
                    //獲取app的版本信息
                    var ver = inf.version;
                    //接口地址,用於獲取服務器上最新的版本號,與本地進行對比。
                    var url = '{你接口的地址}';
                    mui.ajax(url, {
                        data: {
                            apkVersion: ver,
                        },
                        dataType: 'json',
                        type: 'GET',
                        timeout: 60000,
                        success: function(data) {
                            var appVer = data.map.appVersion;
                            if (appVer == null) {
                                return;
                            }
                            plus.io.requestFileSystem(plus.io.PUBLIC_DOWNLOADS, function(fs) {
                                // fs.root是根目錄操作對象DirectoryEntry
                                var directoryReader = fs.root.createReader();
                                directoryReader.readEntries(function(entries) {
                                    for (var i = 0; i < entries.length; i++) {
                                        var fileName = entries[i].name;
                                        var appVerName = appVer + ".apk";
                                        if (fileName != appVerName) {
                                            console.log("不刪除----------")
                                            return;
                                        }
                                        var filePath = "_downloads/" + entries[i].name;
                                        plus.io.resolveLocalFileSystemURL(filePath, function(entry) {
                                            // 可通過entry對象操作test.html文件 
                                            // entry.file(function(file) {
                                            //     console.log(file.name);
                                            // });
                                            entry.remove();
                                        }, function(e) {
                                            // console.log("Resolve file URL failed: " + e.message);
                                        });
                                    }
                                }, function(e) {
                                    // alert("Read entries failed: " + e.message);
                                });
                            });
                        },
                        error: function(xhr, type, errerThrown) {
                            //mui.toast('網絡異常,請稍候再試');
                        }
                    });
                });
            }

四、總結

  之前遺留的問題總算是解決了,之前不知道怎麼,把自己繞進去了。

  不清楚的地方可以看另外一篇:

  不足之處,請大家指教。

  轉發請註明出處:https://www.cnblogs.com/lrj1009IRET/

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

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

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

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

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

如何提高web應用的吞吐量

這篇博文所列舉的優化手段是針對比較傳統項目,但是想提高系統的吞吐量現在時髦的技術還是那些前後端未分離, 使用nginx當成靜態資源服務器去代理我們的靜態資源

是誰限制了Throughput?

當我們對一個傳統的項目進行壓力測試時,很容器就發現,系統的Throughput被數據庫(mysql)限制的死死的,儘管代碼看起來確實沒毛病,邏輯也沒有錯誤,但是過多的請求都被打向了數據庫,數據庫自個開啟大量的IO操作,這樣大的負載甚至會使Linux系統的整體負載驟然飆升,但是反觀我們的系統的吞吐量,呵呵…

將目光投向緩存

既然mysql的抗壓能力限制了我們的系統,那就將數據緩存起來,盡一切可能減少用戶和數據庫之間的直接接觸的次數,這樣我們的系統的吞吐量,同一時間能處理器的請求數量自然會升上去

市面上的緩存技術很多, 比較火爆的是兩款緩存數據庫 Memcache 和 Redis ,

Redis 和 Memcahe的區別

  • Redis不僅僅支持key-value鍵值對類型的數據,同時還支持list,set,hash等數據結構
  • redis支持數據的備份,即master-slaver模式的集群備份
  • Redis是支持數據持久化的,它可以將內存中的數據保存在磁盤中,支持RDB和AOF兩種持久化形式

對Redis進行壓測

# 挨個測試redis中的命令
# 每個數據包大小是3字節
# 100個併發, 發起10萬次請求
redis-benchmark -h 127.0.0.1 -p 6379 -c 100 -n 100000

[root@139 ~]# redis-benchmark -h 127.0.0.1 -p 9997 -c 100 -n 100000
====== PING_INLINE ======
  100000 requests completed in 1.04 seconds
  100 parallel clients
  3 bytes payload
  keep alive: 1

98.68% <= 1 milliseconds // 百分之98.68的請求在1毫秒內完成了
99.98% <= 2 milliseconds 
100.00% <= 2 milliseconds
96525.09 requests per second  // 每秒完成的請求數在9萬六左右


-d  指定數據包的大小,看下面redis的性能還是很強大的
-q  簡化輸出的參數
[root@139 ~]# redis-benchmark -h 127.0.0.1 -p 9997 -q -d 100 -c 100 -n 100000
PING_INLINE: 98619.32 requests per second
PING_BULK: 95877.28 requests per second
SET: 96153.85 requests per second
GET: 95147.48 requests per second
INCR: 95238.10 requests per second
LPUSH: 95328.88 requests per second
RPUSH: 95877.28 requests per second
LPOP: 95328.88 requests per second
RPOP: 97276.27 requests per second
SADD: 96339.12 requests per second
HSET: 98231.83 requests per second
SPOP: 94607.38 requests per second
LPUSH (needed to benchmark LRANGE): 92165.90 requests per second
LRANGE_100 (first 100 elements): 97181.73 requests per second
LRANGE_300 (first 300 elements): 96153.85 requests per second
LRANGE_500 (first 450 elements): 94428.70 requests per second
LRANGE_600 (first 600 elements): 95969.28 requests per second
MSET (10 keys): 98231.83 requests per second

只測試 指定的命令
-t 跟多個命令參數
[root@139 ~]# redis-benchmark -p 9997 -t set,get -q -n 100000 -c 100 
SET: 97276.27 requests per second
GET: 98135.42 requests per second

從上面的壓力測試中,可以看到,Redis的性能是絕對實力, 相當強悍,和mysql相比不是一個量級的, 所以結論很明顯,如果我們在用戶和mysql中鍵加一層redis做緩存,系統的吞吐量自然會上去

於是為了提高系統的抗壓能力,我們將壓力從mysql逐步轉移到redis中

頁面緩存技術

在說頁面緩存之前,我們先說一下在一個傳統的項目中,一個請求的生命周期大概是這樣的: 從瀏覽器發出到服務端, 服務端查詢數據庫獲取結果, 再將結果數據傳遞給模板引擎將數據渲染進html頁面

想提高這個過程的速度,我們可以這樣搞, 頁面緩存, 顧名思義就是將 html 頁面緩存到緩存數據庫中

示例如下:

一開始我們會先嘗試從緩存中獲取出已經渲染好的html源碼響應給客戶端, 響應的格式通過@ResponseBody和produces中的屬性進行控制,告訴瀏覽器自己會返回給它html文本

優點: 將用戶的請求的壓力從mysql轉移到redis, 這點強度對redis單機來說根本不是事

缺點: 很明顯,將請求擴大到頁面級別,數據一致性難免會受到影響, 這也是使用頁面緩存不得不考慮的一點

特點1 : 嚴格控制緩存的時間, 一定別忘了添加過期時間…

特點2 : 原來都是讓thymeleaf自動完成數據的渲染,現在的話,很明顯是我們手動在渲染數據

    @RequestMapping(value = "/to_list",produces = "text/html;charset=UTF-8")
    @ResponseBody
    public String toLogin(Model model, User user, HttpServletResponse response, HttpServletRequest request) {

        // 先從redis緩存中獲取數據
        String html = redisService.get(GoodsKey.goodsList, "", String.class);
        if (html != null)
            return html;

        // 查詢商品列表
        List<GoodsVo> goodsList = goodsService.getGoodsList();
        model.addAttribute("goodsList", goodsList);

        // 使用Thymeleaf模板引擎手動渲染數據
        WebContext springWebContext = new WebContext(request,response,request.getServletContext(),request.getLocale(),model.asMap());
        String goods_list = thymeleafViewResolver.getTemplateEngine().process("goods_list", springWebContext);

        // 存入redis
        if (goods_list!=null){
            redisService.set(GoodsKey.goodsList,"",goods_list);
        }
        return goods_list;
    }

既然都說到這裏了, 就接着說還能怎麼玩吧…

你看, 上面通過手動控制模板引擎的api竟然得到的已經渲染好的html源代碼了, 什麼叫做已經渲染好的? 說白了就是原來我在前端寫:th ${user},這樣的佔位符,現在已經被thymeleaf替換成了 張三 … (說的夠直接吧)

拿到了已經渲染好的源代碼,我們就能通過IO操作,將這個文件寫到系統的某個目錄上去,不知道大家有沒有發現,去逛京東淘寶瀏覽某個商品頁面時,就會發現url是類似這樣的 www.jjdd.com/aguydg/ahdioa/1235345.html

這個後綴123145.html 大概率說明京東使用靜態頁的技術, 這太明智了,面對如此巨大數量的商品信息後綴用数字來表示也不錯,而且速度還快不是?

怎麼實現這種效果呢?

就是上面說的,通過IO將這些源碼的數據寫到Linux中的某一個目錄下面, 文件名就是上面URL中的最後的数字, 通過Nginx做靜態資源服務器將這些xxx.html代理起來, 用戶再訪問的話就走這個靜態頁, 同樣不會接觸數據庫, 而且nginx還支持零拷貝,併發數5萬不是事…
還有,後綴數組最好也別亂寫,直接使用商品id會更好,畢竟是先點擊商品獲取到id,再進入到靜態頁

對象緩存技術

緩存java中的對象, 比如將用戶的信息持久化進redis, 每次用戶查詢自己的信息先從redis中查詢,有的話直接返回,沒有的話再去查詢數據庫, 這樣同樣實現了在用戶和數據庫之間多添加出一層緩存,也可以大大的提高系統的吞吐量

一般會怎麼玩呢?

用戶的請求在查詢數據庫之前先嘗試從redis中獲取對象信息, redis中不存在的話就去數據庫中查詢, 查詢完結果后將這個結果換存進redis

// todo 使用redis做緩存,減少和數據庫的接觸次數
public Label findById(Long labelId) {

    // 先嘗試從緩存中查詢當前對象
    Label label = (Label) redisTemplate.opsForValue().get("label_id" + labelId);

    if (label==null){
        Optional<Label> byId = labelRepository.findById(labelId);
        if (!byId.isPresent()) {
            // todo 異常
        }
        label = byId.get();

        // 將查出的結果存進緩存中
        redisTemplate.opsForValue().set("label_id"+label.getId(),label);
    }
    return label;
}

當用戶update數據 ,先更新數據庫,再刪除/更新redis中響應的緩存

public void update(Long labelId, Label label) {
    label.setId(labelId);
    Label save = labelRepository.save(label);

    // todo 數據庫修改成功后, 將緩存刪除
    redisTemplate.delete("label_id"+save.getId());
    }

當用戶刪除數據,先刪除數據庫中的數據,再刪除redis中的緩存

public void delete(Long labelId) {
    labelRepository.deleteById(labelId);

    // todo 數據庫修改成功后, 將緩存刪除
    redisTemplate.delete("label_id"+labelId);
}

模仿Vue實現頁面靜態化

大家都在說頁面靜態化, 它真的有那麼神奇嗎? 其實也沒有那麼神奇, 說白了吧,傳統的網頁上的數據是通過模板引擎渲染上去的,(比如JSP或者是說thymeleaf這類模板引擎), 做了靜態化的網頁中數據的渲染通過js完成, 而且這個網頁和項目中的 靜態資源比如js,css 這類的文件放在一個目錄下面, 地位和普通的靜態資源相同, 還有個好處就是, 瀏覽器給的福利, 因為瀏覽器對靜態資源是有緩存的, 如果你善於觀察,就會發現有時候重複請求某個網頁,網頁正常显示,但是狀態碼是304… 請求依然會到達服務端,但是服務端會告訴瀏覽器它想訪問的頁面其實沒有變化, 於是瀏覽器就找到本地的緩存使用

時下國內 最火爆的玩靜態頁面時下最火爆的技術就是 Angular.js 以及 Vue.js , 也確實好用, 前幾個月我寫過有關vue的筆記, 感興趣的同學可以去看看

在本篇博客中恰恰好沒用到VUE, 但是實現靜態頁的思路和vue是大差不差的, 同樣是通過js代碼實現頁面的靜態化

  • 首先說後端的代碼怎麼寫?

前後端分離嘛, 自然是json交互,後端通過@ResponseBody控制返回給前端json對象, 而且, 推薦大家也整一個VO對象,用這個VO對象將各式各樣的數據封裝在一起,一次性返回給前端, 這樣看上去,後端確實是簡單,也就是返回一個json對象

  • 前端怎麼寫呢?

第一件事就是將html文件從template文件夾下move到static文件夾下面, 讓這個html文件和js/css文件稱兄道弟

然後是給這個xxx.html該名字, 為啥要改名換目錄呢? 因為SpringBoot是約定大於編碼的, 在什麼目錄下面就是什麼文件, 此外Thymeleaf部分默認的配置信息如下

@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {

    private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;

    public static final String DEFAULT_PREFIX = "classpath:/templates/";

    public static final String DEFAULT_SUFFIX = ".html";

沒辦法,這些配置信息默認就認為類路徑下的templates中都是xxx.html的文件

第二件事是將html標籤中引入的類似thymeleaf這中命名空間都去掉,靜態頁不需要

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>商品列表</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <!-- jquery -->
    <!--<script type="text/javascript" th:src="@{/js/jquery.min.js}"></script>-->
    <script type="text/javascript" th:src="js/jquery.min.js"></script>

第三件事寫一個ajax,當頁面一加載就觸發向後台發請求,獲取數據, 通過jQuery操作各個節點完成數據的渲染

三步打完收工, 看上也不是很複雜, 但是我們的頁面就是已然成為了靜態頁面, 從此她會被瀏覽器緩存起來,只要這個頁面不發生變動,瀏覽器就會一直使用自己的緩存,在網絡上的數據傳輸量有多帶勁自己腦補,系統RT絕對飆升幾個數量級

靜態資源的優化手段

說一下市面上常見的靜態資源優化技術吧:

  • js/css 的壓縮與優化,減少流量
  • 多個js/css組合在一起,減少連接數量
  • Tengine 技術
  • webPack , 使用vue開發時,它就會將一整套vue的依賴打包一個js一個html文件,豈不是爽歪歪?
  • CDN加速技術, 很多雲服務廠商都有提供,而且價格也不貴,將體型大的靜態資源放在CDN上進行加速也是不錯的選擇
  • 使用Nginx做靜態資源代理,而且Nginx就支持零拷貝,還支持將數據文件壓縮后在網絡上傳輸 ,自身的併發量也很強大,當靜態資源服務器它絕對是不二首選, 相信我,你會愛上它的

另外當多個用戶併發修改庫存時,竟然將庫存修改成了負數, 本身使用的數據庫引擎是 innodb是存在行級鎖的, 我們只要修改一下我們的sql就行 加條件 and stock_number > 0

為了防止同一個用戶發送兩次請求,偶爾秒殺到多個商品的情況,我們去miaosha_user表中去建立一個唯一的索引,將userId建立唯一索引,不允許相同的userId出現兩次,從而避免上述的情況

驗證碼技術

  • 好處

讓用戶去輸入驗證碼的好處有很多, 除了驗證用戶的身份信息之外, 最明顯的好處就是分散用戶對系統的壓力, 前端如果不添加圖片驗證碼的可能在1s內系統需要承載1萬併發, 但是添加了圖片驗證碼, 就能將這1萬併發分散到10秒以內,甚至更多

  • 整體的思路:

    圖片驗證碼不過是個image, 所以說前端想展示它,肯定需要一個img標籤, 一個比較不好想的地方是啥呢? 就是這個圖片的路徑,src=啥的問題, 我們可以怎麼做呢? 可以直接通過這個往src中寫入後端的生成imge的Controller的路徑, 每次刷新頁面,它就會往這個路徑中發起請求, Controller中去生成一個image, 通過HttpServletResponse的獲取到輸出流, 將生成的圖片用流的發送會瀏覽器,再加上他是img標籤,這不就ok了?

百度一下如何生成圖片驗證碼一類的技術,確實真的很多,我就不貼代碼了, 感興趣的同學自行百度,代碼一片片的

  • 如何實現點擊圖片完成刷新操作呢?

因為這種圖片是靜態資源,如果你不禁用緩存,這個圖片就會被緩存下來, 要想每次點擊圖片都實現更換驗證碼的話,參考下面的js實現, 添加時間戳

   function refreshImageCode() {
        $("#verifyCodeImg").attr("src","/path/verifyCode?goodsId="+$("#goodsId").val()+"&timestamp="+new Date());
    }

接口限流技術

  • 什麼是接口限流?

舉個例子: 如說我們想限制在一分鐘內單個用戶訪問 A Controller中的a方法的次數不能超過30次, 這其實就是一種接口限流的需求, 可以有效的防止用戶的惡意訪問

  • 如何實現接口限流呢?

其實這件事結合緩存來實現並非是一件難事,比如我就用上面的例子: 不是想對a方法進行限流嗎? 我們就在a方法中添加下面的邏輯

偽代碼如下:

public void a(User user){
    // 校驗user合法性
    // 限流
   Integer count = redis.get(user.getId());
    if(count!=null&&count>15)
      return ; // 到達了指定的闋值,直接返回不允許繼續訪問
    if(count==null){
        redis.set(user.getId(),30,1); // 表示當前用戶訪問了1次, 當前key的有效時間為30s
    }else{
        redis.incr(user.getId());
    }
}
  • 如何不讓限流的邏輯侵染業務代碼呢

我們可以使用攔截器技術, 如果我們的重寫了攔截器的preHandler()方法,它就會在執行Controller中的方法前進行回調, 再配合自定義註解技術, 後面簡直就是為所以為…

示例:

@Component
public class AccessIntercepter extends HandlerInterceptorAdapter {
    // 在方法執行之前進行攔截
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod){
            HandlerMethod hd = (HandlerMethod) handler;
            LimitAccess methodAnnotation = hd.getMethodAnnotation(LimitAccess.class);
            if (methodAnnotation==null)
                return true;

            // 解析註解
            int maxCount = methodAnnotation.maxCount();
            boolean needLogin = methodAnnotation.needLogin();
            int second = methodAnnotation.second();
            // todo
        }
        return true;
    }
}

結語: 最近又到考試周了,今個周六,下周三考試運籌學… 希望自己能平安度過…

我是bloger 賜我白日夢, 歡迎點贊支持

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

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

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

南投搬家前需注意的眉眉角角,別等搬了再說!

農地轉用的特殊案例──北海道知內町太陽能發電廠(上)

文:宋瑞文(加州能源特約撰述)

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

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

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

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

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

美國環團告川普政府 不滿未考量台塑建廠風險

摘錄自2020年1月16日中央社報導

美國環保團體及社區組織今(15日)控告川普政府,抗議發放環境許可讓台灣塑膠公司在南部路易斯安那州建造塑膠廠區;根據計畫,這項建案規模達94億美元(約新台幣2837億元)。

美聯社報導,這起向華盛頓聯邦法院提起的訴訟指控美國陸軍工兵署(US Army Corps of Engineers)未公開這項建廠計畫對環境造成的傷害及對公眾的健康風險,也未適當考量台灣塑膠公司給環境帶來的損害。

位於紐奧良的環保團體「健康灣」(Healthy Gulf)是原告團體之一,執行主任沙爾托(Cyn Sarthou)在新聞稿中表示:「陸軍工兵署正加速發放許可給台塑,這家公司2019年因傾倒數十億顆塑膠粒到德州水道及墨西哥灣沿岸水域而被認定有罪,這完全令人無法接受。」

根據訴訟文書,「健康灣」及其他團體成員擔心破壞濕地會傷害野生生物,讓鄰近地區面對洪澇更加脆弱;也擔心有毒排放物有害健康和環境,和貨車和駁船往來頻繁,會增加噪音、汙染及危險發生的機率。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

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

南投搬家前需注意的眉眉角角,別等搬了再說!

2016中國國際新能源汽車峰會

2016中國國際新能源汽車峰會將于明年3月在北京召開

隨著化石能源、石油資源的日益枯竭,大氣污染和溫室氣體的排放,加之傳統內燃機驅動汽車的能源利用率很低,新能源汽車已成為未來發展的必然趨勢。

新能源汽車是我國戰略性新興產業之一,也是我國應對氣候變化、保障能源安全、減少溫室氣體排放、防治城市空氣污染的重要途徑之一。近10年來,我國把新能源汽車作為未來汽車的主要發展方向,從國家層面給予了極大的關注和支持。去年,我國新能源汽車產銷量較上年增長了三倍,這種爆發式增長,是國家對於新能源汽車不斷加大政策扶持的結果。

在這一市場背景下,2016中國國際新能源汽車峰會將立足於中國新能源汽車行業的實際情況,進一步解析業內人士比較關心的政策法規和最新的技術動向以及未來的發展趨勢,深入探討電控集成系統、無線充電技術以及新能源汽車切入能源互聯網的契機等熱點話題。這裡還將是一個您與政府高層、OEM製造商、行業領袖和專家進行跨國項目交流的最佳平臺。

會議亮點:
•    十三五新能源汽車發展規劃
•    充電新標準出臺和實施時間
•    新能源汽車產業的全球市場戰略
•    探索未來電池新材料技術
•    三元鋰電池最新技術
•    驅動電機的效率提升和性能優化
•    電池管理系統如何提高整包級別的安全性
•    電機控制器如何改善電機運行效率並降低能耗
•    整車控制器的關鍵技術
•    充電樁技術和網路建設
•    無線充電技術的巨大市場前景
•    插電式混合動力的技術和市場
•    電動汽車電氣系統的設計與優化
•    燃料電池汽車未來的商業化路徑
•    新能源商用車市場剖析和關鍵技術
•    開放技術專利能否推動新能源汽車行業加速發展
•    互聯網如何推動新能源汽車產業升級
•    新能源汽車切入能源互聯網的契機
•    與傳統汽車租賃公司的合作模式
•    金融租賃如何解圍新能源汽車的商業模式困局

請聯繫:
Lucy Shi 石小姐
電話: +86 21- 33191337-623
手機:+86 13166042312
郵箱:
會議網址:

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

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

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

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

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

Uber響應環保 在中國大陸推出「電動車日」

中國大陸霧霾嚴重,交通工具被視為兇手之一,故中央政府已開始推出電動車推廣政策,希望能減輕霾害問題。線上叫車業者Uber響應減碳,首度在北京、上海、廣州、成都等中國大陸的13個城市啟動「電動車日」,只要駕駛開電動車載客,就能享受額外獎勵。

中國Uber表示,「電動車日」的活動是為了響應環保減碳而推出。叫車用戶可透過Uber叫車平台呼叫特斯拉、北汽新能源等電動車,或者豐田Corolla Hybrid或Levin等油電混和車。此外,在今年底前以電動車車款加入共乘的車主將可享有額外獎勵,將能鼓勵中國大陸民眾購置電動車。

據統計,Uber上海平台上已有30%的車主駕駛電動車,Uber未來也將與更多電動車品牌合作,透過共乘與綠能發展計畫推廣環保。

根據中新財經網報導,目前中國大陸汽車數量已達2.76億輛,所排放的廢氣對霾害影響甚大。若能以電動車取代燃油車,對於霾害會有正面幫助。中國大陸官方已陸續在各地推出電動公車,並祭出電動車補助措施以及產業補貼,希望能增加民眾採用電動車的比例。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

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

南投搬家前需注意的眉眉角角,別等搬了再說!

利用爬蟲爬取LOL官網上皮膚圖片

  今天在瀏覽網頁時,看到一篇很有意思的文章,關於網絡爬蟲的。該文章是講述如何利用request爬取英雄聯盟官網皮膚圖片。看過文章后覺得挺有用的,把代碼拿過來運行了一下,果真爬取成功。下面給大家分享一下代碼。

  首先得利用cmd命令指示符安裝requests庫,json,re,time。

  安裝完成后,第一步是獲取英雄ID從而為先面判決URL作準備。

def getLOLImages():
    header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36'}
    url_js = 'http://lol.qq.com/biz/hero/champion.js'
    #獲取JS源代碼 Str bytes
    res_js = requests.get(url_js).content
    #轉碼 轉成字符串
    html_js = res_js.decode()
    #正則表達式
    req = '"keys":(.*?),"data"'
    list_js = re.findall(req,html_js)
    #轉成dict
    dict_js = json.loads(list_js[0])
    # print(type(dict_js))
    #定義圖片列表
    pic_list = []
    for key in dict_js:
        # print(key)#英雄ID

第二步就是拼接URL了,通過發現英雄皮膚url的取名方式,我們可以方向最後的数字是不同的。讓后通過此方法來獲取圖片地址。

for i in range(20):
    number = str(i)
    if len(number) == 1:
        hero_num = "00"+number
    elif len(number) == 2:
        hero_num = "0"+number
    numstr = key+hero_num
    url = "http://ossweb-img.qq.com/images/lol/web201310/skin/big"+numstr+".jpg"
    #http://ossweb-img.qq.com/images/lol/web201310/skin/big81000.jpg
    pic_list.append(url)

第三步是獲取圖片名稱,path那行是放置圖片的地址,注意結尾的\\不能丟。

list_filepath = []
    path = "D:\Pycharmdaima\Pachong\LOLTU\\"
for name in dict_js.values():
    for i in range(20):
        file_path = path+name+str(i)+'.jpg'
        list_filepath.append(file_path)

第四步就是下載圖片了。

n = 0
for picurl in pic_list:
    res = requests.get(picurl)
    n += 1
    #獲取狀態碼
    if res.status_code == 200:
        print("正在下載%s"%list_filepath[n])
        time.sleep(1)
        with open(list_filepath[n],'wb') as f:
            f.write(res.content)

最後,調用一下getLOLImages()方法

getLOLImages()

  注意,我第一次用了源碼,後來發現運行太慢,檢查一下源碼后發現代碼末尾調用了一個time.sleep()方法。這樣是為了限制爬取速度,避免速度過快被網站發現而中斷。經過調試,我中途暫停代碼運行,將sleep()方法註釋掉,爬取速度果然加快,而且沒有中斷。

  下面是我的爬取成果:

 

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

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

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

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

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

痞子衡嵌入式:串行EEPROM接口事實標準及SPI EEPROM簡介

  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是EEPROM接口標準及SPI EEPROM

  痞子衡之前寫過一篇文章 ,介紹過并行NOR Flash基本概念。眾所周知,現如今嵌入式非易失性存儲器基本被NOR Flash一統江湖了,但在Flash技術發明之前,EEPROM才是非易失性存儲器的霸主。EEPROM的全稱是”電可擦除可編程只讀存儲器”,即Electrically Erasable Programmable Read-Only Memory,EEPROM技術的發明可是拯救過一大批嵌入式工程師的,畢竟在這之前非易失性存儲器技術的演進分別是ROM(只讀), PROM(只能寫一次), EPROM(紫外線可擦除),擦除方式都不太友好,直到EEPROM的出現才變得人性化。雖說現在Flash是主流,但在較低容量(2Mb以下)尤其是超低容量(1Kb以下)的市場,EEPROM仍然有其不可替代的應用場合。今天痞子衡就來好好聊一聊EEPROM:

一、EEPROM背景簡介

  聊到EEPROM發展史,不得不提浮柵MOSFET,這是一項發明於1967年的技術,它是所有閃存的基礎。1970年,第一款成功的浮柵型器件-EPROM被發明。1979年,大名鼎鼎的SanDisk(閃迪)創始人Eli Harari,發明了世界上首個電可擦除的浮柵型器件即EEPROM。
  講到EEPROM必然要將它和與其相愛相殺的Flash一起對比。關於Flash大家都很熟悉,但其實Flash全稱應該叫Flash EEPROM,它屬於廣義的EEPROM。而本文主角EEPROM,指的是狹義的EEPROM,Flash和EEPROM最大的區別是:Flash按扇區操作,EEPROM按字節操作。Flash的特點是結構簡單,容量可以做得比較大且在大數據量下的操作速度更快,但缺點是操作過程麻煩,所以Flash適於當不需頻繁改寫的程序存儲器。而在有些應用中往往需要頻繁的改寫某些小量數據且需掉電非易失,傳統結構的EEPROM則非常適合。
  EEPROM不像NOR, NAND Flash技術演進得那麼複雜,因此實際上關於EEPROM並沒有成文的標準,即使最知名的电子行業標準之一JEDEC也沒有關於EEPROM的標準出台,不過各大廠商生產的EEPROM似乎都遵從某種約定的事實標準,這在後面介紹的EEPROM接口命令里顯得尤為明顯。

二、Serial EEPROM原理

2.1 Serial EEPROM分類

  從軟件驅動開發角度而言,Serial EEPROM可以從以下幾個方面進一步細分:

地址碼長度:1byte / 2byte / 3byte
通信接口類型:I2C / SPI / Microwire / UNIO Bus / Single-Wire

  本文的主要研究對象是SPI接口的EEPROM。

2.2 SPI EEPROM內存模型

  EEPROM內存單元從大到小一般分為如下4層:Device、Sector、Page、Byte,其中Sector不是必有的,並且Page也只是個結構概念,跟NOR Flash里的Page/Sector意義不一樣,因為Byte就是EEPROM讀寫的最小單元(即可以任意地址隨機訪問),所以你可以把EEPROM當做一個非易失性的RAM。當然有些高端EEPROM中集成了Page/Sector操作命令,這隻是為了讓EEPROM操作效率更高而已。

2.3 SPI EEPROM信號與封裝

  SPI EEPROM一般有8個腳,除去電源Vcc,地GND/Vss,以及SPI四根信號線(CS#, SCK, SI, SO)不言而喻之外,還有兩根特殊的控制信號,即WP#(寫保護)和HOLD#(掛起)。WP#信號主要是從硬件層面上對EEPROM內存進行保護,防止電路上的噪聲干擾篡改了EEPROM里的內容;而HOLD#則提供EEPROM寫操作暫停的功能,當該信號有效的時候,SI信號輸入將被忽略,因此主機可以做其他更高優先級的事情。

  SPI EEPROM雖然只有8pin,但是封裝種類還是比較齊全的,這其中最經典的當屬JEDEC定義的8-lead SOIC,此外還有TSSOP8, UDFN8, WLCSP8,下圖羅列了常見封裝:

2.4 SPI EEPROM接口命令

2.4.1 事實標準

  痞子衡在文章開頭的時候講過,SPI EEPROM並沒有什麼成文的接口命令標準,但是各大廠商生產的SPI EEPROM無一例外都支持下錶的6條命令,即READ(讀內存)、WRITE(寫內存)、WREN(寫使能)、WRDI(寫禁止)、RDSR(讀狀態寄存器)、WRSR(寫狀態寄存器),所以從軟件接口層面而言,這6條命令就是SPI EEPROM事實上的接口命令標準。

  除了6條標準命令外,SPI EEPROM內部還有一個8bit的狀態寄存器,用於反饋命令執行狀態,這8bit狀態寄存器的位定義也是存在如下錶所示的事實標準的:

  不考慮寫保護特性的話,bit0 – RDY#和bit1 – WEL是比較常用的,RDY#位主要用於標示所有涉及改變內存或狀態寄存器的命令的執行結果,WEL位則保存了上一次WREN和WRDI命令的執行結果。狀態寄存器中的其他兩處定義bit7 – WPEN, bit[3:2] – BP[1:0]則主要與寫保護特性有關,它們的具體作用如下:

2.4.2 廠商個性化

  除了6條事實標準的命令外,有些廠商還實現了一些自定義的命令,這些命令並不一定通用,一般用於較大容量(3byte地址碼,512Kb以上)的EEPROM上。痞子衡找了一款非常經典的EEPROM,來自Microchip的25AA系列(25AA1024),讓我們看看它有啥個性化的命令。這顆EEPROM容量為1Mb,屬於大容量EEPROM,為了提高EEPROM操作效率,Microchip為這顆EEPROM增加了Page/Sector/Chip Erase命令,使得擦除操作效率變高了,如果沒有這些個性化擦除命令,那麼只能通過標準WRITE命令去手動實現擦除操作,既麻煩又低效。

2.5 SPI EEPROM數據速率

  數據存取速率是個重要的技術指標,咱們來看看SPI EEPROM的讀寫時序,前面痞子衡在講EEPROM分類的時候提到過EEPROM地址碼有1byte/2byte/3byte之分,地址碼的區別主要體現了EEPROM讀寫時序上。對於讀時序,在SPI總線發完READ(0x03)命令后,緊接着要發送想要讀取的內存地址,地址碼不同,發送的地址字節數也不同。對於容量大於512Kb的EEPROM(即地址碼為3byte),顯然要發送3byte的地址,才能確定要讀的數據所在地址,然後才能進行讀數據操作。

  而對於容量小於等於512Kb的EEPROM,關於1byte和2byte地址碼區分,有一個特殊的設計,即對於512byte容量的EEPROM,按容量來說其屬於2byte地址碼範疇,READ命令后需要發送2byte地址,但實際上只需要發送1byte地址(A7-A0),而最高地址位A8放在了READ命令碼bit3里,這樣可以節省1個字節的地址碼。因此1Kb – 512Kb容量的EEPROM地址碼為2byte,512byte及以下容量的EEPROM地址碼為1byte,如下圖所示:

  從上面讀時序可以看出,READ命令碼和地址碼發完之後幾乎沒有等待周期,就可以直接讀取EEPROM中數據,因此EEPROM讀數據速率完全取決於SPI總線速率,所以我們只需要打開EEPROM數據手冊,看看它最高能支持多高的SPI總線速率即可(常見的有2MHz/5MHz/10MHz/20MHz)。
  對於寫時序,就稍微複雜一些了,這裏不考慮地址碼區別,以2byte地址為例。首先在發送WRITE命令之前需要發送一個WREN命令使能寫操作,因為默認EEPROM在執行完上一次寫操作後會恢複寫禁止狀態,在發送WRITE命令進行寫操作之前必須保證EEPROM處於寫使能狀態。

  確保EEPROM進入寫使能狀態后,開始發送WRITE命令,然後是地址碼,接着是要寫入的數據,痞子衡前面講過Page在EEPROM是個結構概念,但其實也跟WRITE命令有關,因為EEPROM既可以按byte去寫,也可以按Page去寫,如果需要存入連續的數據,顯然按Page去寫效率比按Byte寫入更高。這裏需要注意的是,WRITE命令後面跟的字節數不能超過要寫入的首地址所在Page剩餘的字節數。下圖示例的Page寫時序最大byte數為16/32,是因為示例EEPROM的page size即16/32 byte。

  當一次WRITE時序內要寫入的數據全部發送完成之後,底下便進入等待周期,與READ時序不同的是,WRITE時序有等待周期,因為EEPROM內部要將緩存在page buffer里的數據編程到真正的內存空間里,這需要時間。用戶只能通過不斷地發送如下RDSR命令去讀取狀態寄存器bit0 – RDY#來判斷WRITE等待周期是否結束。因此寫時序速率不僅僅取決於SPI總線速率,還取決於等待周期時長。

  如果想快捷地了解SPI EEPROM的性能,最簡單的就是打開SPI EEPROM手冊,看首頁的feature介紹,如下是25AA080的簡要feature:

• Max. Clock 10 MHz
• 1024 x 8-bit Organization
• 16 Byte Page (‘C’ version devices)
• 32 Byte Page (‘D’ version devices)
• Self-Timed Erase and Write Cycles (5 ms max.)
• Block Write Protection:
  - Protect none, 1/4, 1/2 or all of array
• Built-In Write Protection:
  - Power-on/off data protection circuitry
  - Write enable latch
  - Write-protect pin
• Sequential Read
• High Reliability:
  - Endurance: > 1M erase/write cycles
  - Data retention: > 200 years

三、SPI EEPROM產品

  最後痞子衡收集了可以售賣SPI EEPROM芯片的廠商及產品系列:

廠商 芯片系列 官方網址
Microchip
Atmel
25AA, 25LC
AT25
ST M95
Onsemi CAT25
Renesas R1EX25
Rohm BR25A, BR25G, BR25H, BR25S
Fudan Micro FM25

  至此,EEPROM接口標準及SPI EEPROM痞子衡便介紹完畢了,掌聲在哪裡~~~

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

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

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

南投搬家前需注意的眉眉角角,別等搬了再說!

Ansibile之playbook初識

  一、playbook簡介

  ansiblie的任務配置文件被稱為playbook,俗稱“劇本”,每一個劇本(playbook)中都包含了一系列的任務,這每個任務在ansible中又被稱為“戲劇”(play),一個劇本中包含多齣戲劇。。

  前文我們了解了ansible有兩種執行方式ad-hoc和ansible-playbook,ad-hoc主要用於臨時命令的執行,而playbook我們可以理解為ad-hoc的集合,有點類似shell腳本,ad-hoc就相當於shell腳本里的某條任務語句,playbook就相當於整個shell腳本。playbook是由一個或多個“play”組成的列表,play的主要功能在於將預定義的一組主機,裝扮成事先通過ansible中的task定義好的角色。task實際是調用ansible的一個模塊,將多個play組織在一個playbook中,即可以讓他們聯合起來,按事先編排的機制執行預定義的動作。

 如以上圖示,用戶可以把多條任務(ad-hoc任務)寫到playbook中,用戶用ansible-playbook命令調用執行編排好的playbook,ansible會讀取playbook中的每一條play和task,並按照playbook中的順序從上至下依次執行,ansible會調用每個task中定義的模塊去依次執行相應的任務,並按照playbook中指定的主機去主機清單里匹配對應的主機,然後通過ssh認證,把編譯好的相應的任務文件發送到對應的主機或網絡設備上執行,最後返回執行的狀態。

  二、YAML簡介

  playbook採用yaml語言編寫,yaml是一個可讀性高的用來表達資料序列格式的語言,它參考了其他很多種語言,包括:XML、C語言、python、perl以及电子郵箱格式RFC2822等。Clark Evans在2001年首次發表了這種語言,另外Ingy döt Net與Oren Ben-Kiki也是這語言的共同設計者。YAML( YAML Ain’t Markup Language),即yaml不是標記語言。不過在開發這種語言時,yaml的意思其實是:”Yet Another Markup Language”(仍是一種標記語言)

  ymal特性

  1)YAML的可讀性好

  2)YAML和腳本語言的交互性好

  3)YAML使用實現語言的數據類型

  4)YAML有一個一致的信息模板

  5)YAML易於實現,可以基於流程處理,表達能力強,擴展性好

更多的內容及規範請參考官方文檔

  三、playbook語法簡介

  1)需要以“—”(3個減號)開始,且需頂行首寫。另外還有選擇性的連續三個點號(…)用來表示文件的結尾。

  2)次行開始正常寫playbook的內容,建議次行寫該playbook的功能,當然不寫也是可以的。

  3)使用“#”號註釋代碼。

  4)縮進必須統一,不能空格tab混用。

  5)縮進的級別必須是一致的,同樣的縮進代表同樣級別,程序判別配置的級別是通過縮進結合換行來實現的。

  6)YAML文件內容和Linux系統大小寫判斷方式一直,區分大小寫(大小寫敏感),k/v的值均大小寫敏感。

  7)k/v的值可同行寫也可換行寫。同行使用“:”分隔,換行寫需要以“-”分隔。

  8)v可以是字符串,也可以另外一個列表,當然也可以是字典。

  9)一個完整的代碼塊功能最少需要有name:xxx(對任務的描述)。

  10)一個name只能包括一個task

  11)yaml文件擴展名通常為yml或yaml

list:列表,其所有元素均使用“-”開頭

示例:

---
# A list of tasty fruits

- apple
- orange
- strawberry
- mango
~           

dictionary:字典,通常由多個key與value構成

示例:

---
#An employee record
name: example developer
job: developer
skill: elite  

當然也可以將key:value放置於{}中進行表示,用“,”分隔多個key:value

示例:

---
#An employee record
{name: example developer,job: developer, skill: elite}
~                                                         

  YAML的語法和其他高階語言類似,並且可以簡單表達清單、散列表、標量等數據結構。其結構(Structure)通過空格來展示,序列(Sequence)里的項用”-“來代表,Map里的鍵值對用”:”分隔。

示例:

---
name: John Smith
age: 41
gender: Male
spouse:
  name: Jane Smith
  age: 37
  gender: Female
children:
  - name: Jimmy Smith
    age: 17
    gender: Male
  - name: Jenny Smith
    age: 13
    gender: Female
~                    

  四、playbook核心元素

  1)hosts  :指定執行任務的遠程主機列表(主機清單定義的主機組或單個主機,支持前面的說的主機模式匹配)

  2)tasks  :任務集

  3)varniables  :內置變量或自定義變量在playbook中調用

  4)templates  :模板,可替換模板文件中的變量並實現一些簡單邏輯的文件

  5)handlers  和  notity結合使用,由特定條件出發的操作,滿足條件方才執行,否則不執行

  6)tags標籤  :給指定的任務貼上標籤,我們在執行playbook的時候可以根據標籤選擇性的挑選部分代碼執行,如 ansible-playbook -t tagsname useradd.yml  ,這條命令的意思就是在useradd.yml中挑選標籤名為tagsname的任務執行

   五、playbook基礎組件

  1)hosts:

    playbook中的每一個play的目的都是為了讓特定主機以某個指定的用戶身份執行任務。hosts用於指定要執行任務的主機,須事先定義在主機清單中。hosts指定主機的形式同樣支持像主機清單中定義的那樣,支持通配,支持主機模式匹配與或非,支持IP地址,當然也支持混合匹配與或非。

示例:在websers組,但不再dbsers組,可以這樣定義hosts

---
- hosts: websers:!dbsers

  2)remote_user:可用於host和task中,也可以通過指定其通過sudo的方式在遠程執行任務,其可用於play全局或某個任務;此外,甚至可以在sudo時使用用sudo_user指定sudo時切換的用戶,如下所示

---
- hosts: websers:!dbsers
  remote_user: root

  tasks:
    - name: test connection
      ping:
      remote_user: qiuhom
      sudo: yes
      sudo_user: qiuping

  說明:默認sudo 為root,上例指定了sudo_user 為qiuping,上述任務同sudo -u qiuping ping xxxx(代表某主機)命令一樣的意思,當然在使用sudo 時 我們還需要在目標主機上對qiuhom授權,要讓qiuhom這個用戶具有代表qiuping的權限去執行ping命令。

  3)task列表和action:play的主體部分是task list,task list 中的各任務按次序逐個在hosts中指定的所有主機上執行,即在所有主機上完成第一個任務后,再開始第二個任務;task的目的是使用指定的參數執行模塊,而在模塊參數中可以使用變量,模塊執行時是冪等的,這意味着多次執行時是安全的,其結果均一致;每個task都應該有其name,用於playbook的執行結果輸出,建議其內容能清晰地描述任務步驟,如未提供name,則action的結果將用於輸出。

  tasks:任務列表,它有兩種格式如下

    (1)action: module arguments

    (2)module: arguments        ##建議使用

   注意:shell模塊和command模塊後面跟的是命令,而非key=value

如果某項任務的狀態在運行後為changed時,可通過“notify”通知給相應的handlers;當然任務可以通過“tags”打標籤,可以在ansible-playbook命令上使用-t指定進行指定其標籤名調用。

示例:

[qiuhom@test ~]$cat test.yml 
---
- hosts: websers:!dbsers
  remote_user: root

  tasks:
    - name: test connection
      ping:
      remote_user: qiuhom
      sudo: yes
      sudo_user: qiuping 
      tags: test
    - name: test command
      shell: /bin/ls /home/qiuhom/
[qiuhom@test ~]$ansible-playbook -t test test.yml 

  說明:用-t 指定標籤名,表示只運行所指定標籤所在的任務,當然同名的標籤可以在多條任務中,一個任務也可以有多個標籤。

如果命令或腳本的退出碼不為零,可用使用如下方式忽略或跳過繼續執行以下代碼

---
- hosts: websers:!dbsers
  remote_user: root

  tasks:
    - name: run this command and ignore the result
      shell: /usr/sbin/ip addr show eth0 || /bin/true
    - name: run this command and ignore the result
      shell: /usr/sbin/ip addr show eth0
      ignore_errors: True

  說明:兩種方式都可以跳過出錯的命令而不打斷playbook,繼續執行以下的代碼,前者使用的短路或的特性,後者使用ignore_errors參數來控制

  六、playbook運行的方式

ansible-playbook <filename.yml> ... [options]

常用選項:

  -C , –check  : 只檢查可能會發生的改變,但不真正執行操作,相當於空跑一遍playbook,測試下是否和自己預想的結果一樣,但它不會真正的去遠端主機上執行。常用於測試寫的playbook語法是否有誤。

  –list-hosts  :列出playbook指定運行任務所匹配的主機

  –list-tags    :列出playbook中所有標籤名稱列表

  –list-tasks  :列出playbook中所有任務名稱及標籤名稱

  –limit 主機列表   :只針對指定主機列表中的主機執行當前playbook(指定主機列表必須是在playbook里定義的主機列表範圍內)

  -v,-vv,-vvv       :  显示執行playbook的過程,-v,显示較簡單,-vv显示較詳細,-vvv显示整個過程(非常詳細)

[root@test ~]#cat test.yml 
---
- hosts: websers
  remote_user: root

  tasks:
    - name: run this command 
      shell: hostname
      tags: hostname
      ignore_errors: True
    - name: show ip addr
      shell: /sbin/ip addr show
      tags: showip
[root@test ~]#ansible-playbook test.yml --list-hosts

playbook: test.yml

  play #1 (websers): websers    TAGS: []
    pattern: [u'websers']
    hosts (2):
      192.168.0.128
      192.168.0.218
[root@test ~]#ansible-playbook test.yml --list-tags

playbook: test.yml

  play #1 (websers): websers    TAGS: []
      TASK TAGS: [hostname, showip]
[root@test ~]#ansible-playbook test.yml --list-tasks

playbook: test.yml

  play #1 (websers): websers    TAGS: []
    tasks:
      run this command  TAGS: [hostname]
      show ip addr      TAGS: [showip]
[root@test ~]#ansible-playbook test.yml --limit 192.168.0.218

PLAY [websers] ********************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************
ok: [192.168.0.218]

TASK [run this command] ***********************************************************************************************
changed: [192.168.0.218]

TASK [show ip addr] ***************************************************************************************************
changed: [192.168.0.218]

PLAY RECAP ************************************************************************************************************
192.168.0.218              : ok=3    changed=2    unreachable=0    failed=0   

[root@test ~]#ansible-playbook test.yml --limit 192.168.0.218 -v
Using /etc/ansible/ansible.cfg as config file

PLAY [websers] ********************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************
ok: [192.168.0.218]

TASK [run this command] ***********************************************************************************************
changed: [192.168.0.218] => {"changed": true, "cmd": "hostname", "delta": "0:00:00.002139", "end": "2019-11-16 23:11:02.996962", "rc": 0, "start": "2019-11-16 23:11:02.994823", "stderr": "", "stderr_lines": [], "stdout": "localhost.localdomain", "stdout_lines": ["localhost.localdomain"]}

TASK [show ip addr] ***************************************************************************************************
changed: [192.168.0.218] => {"changed": true, "cmd": "/sbin/ip addr show", "delta": "0:00:00.002604", "end": "2019-11-16 23:11:03.733004", "rc": 0, "start": "2019-11-16 23:11:03.730400", "stderr": "", "stderr_lines": [], "stdout": "1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN \n    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n    inet 127.0.0.1/8 scope host lo\n    inet6 ::1/128 scope host \n       valid_lft forever preferred_lft forever\n2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000\n    link/ether 00:0c:29:e8:f6:7b brd ff:ff:ff:ff:ff:ff\n    inet 192.168.0.218/24 brd 192.168.0.255 scope global eth0\n    inet6 fe80::20c:29ff:fee8:f67b/64 scope link \n       valid_lft forever preferred_lft forever\n3: pan0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN \n    link/ether d2:7a:38:cf:27:60 brd ff:ff:ff:ff:ff:ff", "stdout_lines": ["1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN ", "    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00", "    inet 127.0.0.1/8 scope host lo", "    inet6 ::1/128 scope host ", "       valid_lft forever preferred_lft forever", "2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000", "    link/ether 00:0c:29:e8:f6:7b brd ff:ff:ff:ff:ff:ff", "    inet 192.168.0.218/24 brd 192.168.0.255 scope global eth0", "    inet6 fe80::20c:29ff:fee8:f67b/64 scope link ", "       valid_lft forever preferred_lft forever", "3: pan0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN ", "    link/ether d2:7a:38:cf:27:60 brd ff:ff:ff:ff:ff:ff"]}

PLAY RECAP ************************************************************************************************************
192.168.0.218              : ok=3    changed=2    unreachable=0    failed=0   

[root@test ~]#

  說明:–limit 所指定的主機必須是在playbook中所指定的主機範圍內。

   七、playbook vs shell scripts

  1)shell腳本如下:

#!/bin/bash
# 安裝Apache
yum install --quiet -y httpd
# 複製配置文件
cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
cp/tmp/vhosts.conf /etc/httpd/conf.d/
# 啟動Apache,並設置開機啟動
service httpd start
chkconfig httpd on

  2)playbook

---
- hosts: websers
  remote_user: root

  tasks:
    - name: create apache group
      group: name=apache gid=80 system=yes
    - name: create apache user
      user: name=apache uid=80 group=apache system=yes shell=/sbin/nologin home=/var/www/html 
    - name: install httpd
      yum: name=httpd
    - name: copy config file
      copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
    - name: copy config 2 file
      copy: src=/tmp/vhosts.conf dest=/etc/httpd/conf.d/
    - name: start httpd service
      service: name=httpd state=started enabled=yes     

  說明:兩者都是實現同樣的目的,很明顯playbook的優勢要比腳本的優勢多,playbook 可以針對很多台主機進行任務執行,而腳本只可以在某一台主機上執行;腳本重複執行沒有冪等性,很有可能帶來很多錯誤,而playbook卻不會有這樣的苦惱。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

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

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

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

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

前端Leader你應該知道的NPM包管理機制

npm install 命令

首先總結下npm 安裝一個模塊包的常用命令。

/* 模塊依賴會寫入 dependencies 節點 */

npm install moduleName

npm install -save moduleName

npm install -S moduleName 

/* 模塊依賴會寫入 devDependencies 節點 */

npm install -save-dev moduleName

npm install -D moduleName

/* 全局安裝模塊包 */

npm install -g moduleName

/* 安裝特定版本的包 */

npm install 包名@版本號

/* 通過地址安裝git倉庫 */

npm install git+https://github.com/itwmike/axios.git

npm install git+ssh://git@github.com:itwmike/axios.git
 
/* 安裝特定分支或Tag的git倉庫 */

npm install git+https://github.com/itwmike/axios.git#tag

/* 通過用戶名安裝git倉庫 */ 

npm install github:帳號/倉庫名 # npm install github:itwmike/axios

npm install github:帳號/倉庫名

  

npm 依賴包版本號

npm 所有node包都使用語義化版本號,規則要求如下:  

  • 每個版本號都形如1.2.3,由三個部分組成,依次叫做“主版本號(major)”、“次版本號(minor)”和“修訂號(patch)” 。

  • 當新版本無法兼容基於前一版本的代碼時,則提高主版本號 。

  • 當新版本新增了功能與特性,但仍兼容前一版本的代碼時,則提高次版本號 。

  • 當新版本僅僅修正漏洞或者增強效率,仍然兼容前一版本代碼,則提高修訂號。

默認使用 npm install -save 下載的都是最新版本,同時會在package.json 文件中登記一個最優版本號,如下形式:

"dependencies": {
  "axios": "^0.19.0"
},

  

最優版本號前面會多出一個“標記”,這個標記有啥意義?它的寫法又有哪些?

 

npm install 都做了哪些事?

拿到一個node項目時首要做法是運行 npm install 命令,這個命令將 package.json 文件中的依賴包自動解析並安裝,這也是項目能夠本地運行的前置條件。那如此簡單的一條命令,npm 背後又做了哪些不為人知的事呢?

Number One

自 npm 5.0后,項目中如果沒有 package-lock.json 文件的時候,npm 會自動幫我們生成。該文件的主要作用是記錄依賴包之間的具體版本號,對包版本有一個鎖定的意義,項目開發中應該將此文件上傳到git等版本控制工具(博主為此經歷了血淋淋的慘痛教育)。

Number Two

檢測本地包是否已經下載。如果本地 node_modules 下已經存在和 package-lock.json 中版本一致的包,則不會重新下載。

Number Three

下載依賴節點中對應的模板包。下載規則是:如果 package-lock.json 文件存在,則按照該文件中記錄的版本號下載對應的模塊包;如果文件不存在或文件中沒有該包的記錄,此時會按照版本號的標記(上面已講)規範下載並同時更新到 package-lock.json。

了解了 package-lock.json 的作用后,筆者有個疑問:手動修改 package.json 中的包版本號后運行 npm install 命令會下載新包么?

帶着這個疑問,筆者做了實驗,得出如下結論:

  • 如果新舊版本號差距較大,比如從 ^2.5.2 變為 2.6.0 ,那麼會下載最新包並且更新 package-lock.json 。

  • 如果新舊版本號差距較小,比如從 ^2.5.2 變為 2.5.4,那麼不會更新。

總之是否更新要看特定情況,取決於 package.json中版本號的標記和 package-lock.json 是否一致。

cnpm install 探索

cnpm 是淘寶 npm 鏡像,在國內很受歡迎,雖然筆者並不喜歡使用。那 cnpm 和 npm 對包的管理是否一樣呢?

  • cnpm install 並不會生成 package-lock.json

  • cnpm install 並不受 package-lock.json 的約束,它會按照版本號標記規則下載依賴包

 

由此可見,我們在項目中使用 cnpm 的時候一定要慎重,因為很可能團隊成員每個人使用的依賴包版本都不相同,造成打包后的結果也不同。

如果團隊要使用 cnpm,請使用固定版本號的方式安裝依賴包如:cnpm install -E moduleName

 

本文轉載自:

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

【其他文章推薦】

網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

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

南投搬家前需注意的眉眉角角,別等搬了再說!