❶ 下列軟體中,________屬於系統軟體。 A、CAD B、Word C、匯編程序 D、C語言編譯程序
C、匯編程序 D、C語言編譯程序
❷ linux裡面systemd是什麼
Systemctl是一個systemd工具,主要負責控制systemd系統和服務管理器。
Systemd是一個系統管理守護進程、工具和庫的集合,用於取代System V初始進程。Systemd的功能是用於集中管理和配置類UNIX系統。
啟動及服務
大多數主流發行版要麼已經採用 Systemd,要麼即將在下個發布中採用(如 Debian 和 Ubuntu)。在本教程中,我們使用 Fedora 21(該發行版已經是 Systemd 的優秀實驗場地)的一個預覽版進行演示,但不論您用哪個發行版,要用到的命令和注意事項都應該是一樣的。這是 Systemd 的一個加分點:它消除了不同發行版之間許多細微且瑣碎的區別。
在終端中輸入 ps ax | grep systemd,看到第一行,其中的數字 1 表示它的進程號是1,也就是說它是 Linux 內核發起的第一個程序。因此,內核一旦檢測完硬體並組織好了內存,就會運行 /usr/lib/systemd/systemd 可執行程序,這個程序會按順序依次發起其他程序。(在還沒有 Systemd 的日子裡,內核會去運行 /sbin/init,隨後這個程序會在名為 SysVinit 的系統中運行其餘的各種啟動腳本。)
Systemd 的核心是一個叫單元unit的概念,它是一些存有關於服務service(在運行在後台的程序)、設備、掛載點、和操作系統其他方面信息的配置文件。Systemd 的其中一個目標就是簡化這些事物之間的相互作用,因此如果你有程序需要在某個掛載點被創建或某個設備被接入後開始運行,Systemd 可以讓這一切正常運作起來變得相當容易。(在沒有 Systemd 的日子裡,要使用腳本來把這些事情調配好,那可是相當醜陋的。)要列出您 Linux 系統上的所有單元,輸入以下命令:
systemctl list-unit-files
現在,systemctl 是與 Systemd 交互的主要工具,它有不少選項。在單元列表中,您會注意到這兒有一些格式化:被啟用enabled的單元顯示為綠色,被禁用disabled的顯示為紅色。標記為「static」的單元不能直接啟用,它們是其他單元所依賴的對象。若要限制輸出列表只包含服務,使用以下命令:
systemctl list-unit-files --type=service
注意,一個單元顯示為「enabled」,並不等於對應的服務正在運行,而只能說明它可以被開啟。要獲得某個特定服務的信息,以 GDM (Gnome Display Manager) 為例,輸入以下命令:
systemctl status gdm.service
這條命令提供了許多有用的信息:一段給人看的服務描述、單元配置文件的位置、啟動的時間、進程號,以及它所從屬的 CGroups(用以限制各組進程的資源開銷)。
如果您去查看位於 /usr/lib/systemd/system/gdm.service 的單元配置文件,您可以看到各種選項,包括要被運行的二進制文件(「ExecStart」那一行),相沖突的其他單元(即不能同時進入運行的單元),以及需要在本單元執行前進入運行的單元(「After」那一行)。一些單元有附加的依賴選項,例如「Requires」(必要的依賴)和「Wants」(可選的依賴)。
此處另一個有趣的選項是:
Al Alias=display-manager.service
當您啟動 gdm.service 後,您將可以通過 systemctl status display-manager.service 來查看它的狀態。當您知道有顯示管理程序display manager在運行並想對它做點什麼,但您不關心那究竟是 GDM,KDM,XDM 還是什麼別的顯示管理程序時,這個選項會非常有用。
使用 systemctl status 命令後面跟一個單元名,來查看對應的服務有什麼情況。
❸ 如何使用systemd 取代init
一、CentOS的Services使用了systemd來代替sysvinit管理
1、systemd的服務管理程序:
systemctl是主要的工具,它融合之前service和chkconfig的功能於一體。可以使用它永久性或只在當前會話中啟用/禁用服務。
systemctl可以列出正在運行的服務狀態,如圖:
systemd-cgls以樹形列出正在運行的進程,它可以遞歸顯示控制組內容。如圖:
2、如何啟動/關閉、啟用/禁用服務?
啟動一個服務:systemctl start postfix.service
關閉一個服務:systemctl stop postfix.service
重啟一個服務:systemctl restart postfix.service
顯示一個服務的狀態:systemctl status postfix.service
在開機時啟用一個服務:systemctl enable postfix.service
在開機時禁用一個服務:systemctl disable postfix.service
查看服務是否開機啟動:systemctl is-enabled postfix.service;echo $?
查看已啟動的服務列表:systemctl list-unit-files|grep enabled
說明:啟用服務就是在當前「runlevel」的配置文件目錄/etc/systemd/system/multi-user.target.wants/里,建立/usr/lib/systemd/system裡面對應服務配置文件的軟鏈接;禁用服務就是刪除此軟鏈接。如圖:
查看了/usr/lib/systemd/system 里的文件,語法跟舊版/etc/init.d/里的系統服務腳本完全不同了。
二、修改系統運行級別:
1、systemd使用比sysvinit的運行級更為自由的target替代。第3運行級用multi-user.target替代。第5運行級用graphical.target替代。runlevel3.target和runlevel5.target分別是指向 multi-user.target和graphical.target的符號鏈接。
可以使用下面的命令切換到「運行級別3 」:
systemctl isolate multi-user.target或systemctl isolate runlevel3.target
可以使用下面的命令切換到「運行級別5 」:
systemctl isolate graphical.target或systemctl isolate runlevel5.target
2、如何改變默認運行級別?
systemd使用鏈接來指向默認的運行級別。在創建新的鏈接前,可以通過下面命令刪除存在的鏈接: rm /etc/systemd/system/default.target
默認啟動運行級別3 :
ln -sf /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
默認啟動運行級別5 :
ln -sf /lib/systemd/system/graphical.target/etc/systemd/system/default.target
systemd不使用/etc/inittab文件。
3、如何查看當前運行級別?
舊的runlevel命令在systemd下仍然可以使用。可以繼續使用它,盡管systemd使用 『target』 概念(多個的 『target』 可以同時激活)替換了之前系統的runlevel。
等價的systemd命令是systemctl list-units –type=target
三、其他配置工具:
1、setup和ntsysv工具還是保留了,但是功能已大大減弱,以前ntsysv工具可以控制所有系統服務的自啟動,現在只能控制少部分服務。
2、/etc/resolv.conf這個DNS配置文件沒變。
3、/etc/sysconfig/network-scripts/ifcfg-ens192網卡配置文件名字和一些選項有所變化。
4、引導方式改用grub2引導,grub2有如下特點:1、模塊化設計;2、支持多體系硬體架構;3、支持國際化多語言;4、獨立內存管理;5、支持腳本語言。
附:systemd簡介
systemd是Linux下的一種init軟體,由Lennart Poettering帶頭開發,並在LGPL 2.1及其後續版本許可證下開源發布。其開發目標是提供更優秀的框架以表示系統服務間的依賴關系,並依此實現系統初始化時服務的並行啟動,同時達到降低Shell的系統開銷的效果,最終代替現在常用的System V與BSD風格init程序。
與多數發行版使用的System V風格init相比,systemd採用了以下新技術:
採用Socket激活式與匯流排激活式服務,以提高相互依賴的各服務的並行運行性能;
用cgroups代替PID來追蹤進程,以此即使是兩次fork之後生成的守護進程也不會脫離systemd的控制。
從設計構思上說,由於systemd使用了cgroup與fanotify等組件以實現其特性,所以只適用於Linux。
❹ Systemd 的詳細啟動過程是怎樣的
您可以通過pstree命令查看啟動了哪些服務,使用systemd-analyseplot>boot.svg生成一張啟動詳細信息矢量圖,然後用圖像瀏覽器或者網頁瀏覽器打開查看
❺ 怎麼將腳本作為linux的systemd
傳統方式,Unix和Linux服務(daemons)由SysV的init腳本啟動.這些服務寫成Bourne Shell腳本,通常駐留在像/etc/rc.d/init.d/這樣的目錄里,調用時有一個或幾個參數,比如start, stop或restart, 用來控制服務的開始,停止和重啟. 開始服務包括調用守護程序的代碼, 守護程序再fork一個後台進程.Shell腳本很慢,難以閱讀,冗長而脆弱. 盡管shell腳本極其靈活(畢竟,腳本本身就是代碼)有些事兒很難拿腳本來完成,比如:安排並發執行的順序,正確的監督進程或只是詳盡的配置執行上下文. systmed可以與腳本兼容, 但下面我們馬上就會提到,在安裝所有守護進程的時候推薦安裝原生的systemd服務文件. SysV 的啟動腳本需要根據發行版的不同做出調整,systemd的服務文件則兼容任何發行版中運行的systemd. 接下來是一個簡潔的入門手冊:如何把SysV的shell腳本轉換成一個systemd服務文件。理想情況下,上位的軟體應該在tar包里發行和安裝systemd的服務文件. 如果你已經根據入門手冊成功的把某個上位軟體SysV腳本轉換成功了,一個不錯的做法是把轉換成功的文件作為補丁提交給那個上位軟體. 後續的文章將會討論如何准備這樣一個補丁, 現在可以告訴你的是systemd的daemon(7)用戶手冊中有與之相關的很多有用信息.
開始吧,作為例子,我們將把ABRT守護進程的init腳本轉換成systemd的服務文件。ABRT是每個Fedora安裝版的標准組件,它是自動Bug報告工具(Automatic Bug Reporting Tool)的縮寫,比如,它提供收據crash mps服務。它的SysV腳本上傳到這里了。
❻ systemd的.service文件如何編寫
沒辦法發鏈接
google
ArchWiki,Systemd條目,教你如何編寫systemd unit
❼ 如何編寫 Systemd 服務文件
一種以 .service 結尾的單元(unit)配置文件,用於控制由 systemd 控制或監視的進程。簡單說,用於後台以守護精靈(daemon)的形式運行程序。
編寫 Systemd service
基本結構
Systemd 服務的內容主要分為三個部分,控制單元(unit)的定義、服務(service)的定義、以及安裝部分。
和 SysV init 腳本的差異
過去,*nix 服務(守護精靈)都是用 SysV 啟動腳本啟動的。SysV 啟動腳本就是 Bash 腳本,通常在 /etc/init.d 目錄下,可以被一些標准參數如 start,stop,restart 等調用。啟動該腳本通常意味著啟動一個後台守護精靈(daemon)。shell 腳本常見的缺點就是,慢、可讀性不強、太詳細又很傲嬌。雖然它們很靈活(畢竟那就是代碼呀),但是有些事只用腳本做還是顯得太困難了,比如安排並列執行、正確監視進程,或者配置詳細執行環境。
SysV 啟動腳本還有一個硬傷就是,臃腫,重復代碼太多。因為上述的「標准參數」必須要靠各個腳本來實現,而且各個腳本之間的實現都差不多(根本就是從一個 skeleton 骨架來的)。而 Systemd 則進行了統一實現,也就是說在 Systemd service 中完全就不需要、也看不到這部分內容。這使得 Systemd 服務非常簡明易讀,例如 NetworkManager 這一重量級程序的服務,算上注釋一共才有 19 行。而它相應的 SysV 啟動腳本頭 100 行連標准參數都沒實現完。
Systemd 兼容 Sysv 啟動腳本,這也是為什麼這么久我們仍然需要一個 systemd-sysvinit 軟體包的原因。但是根據以上理由,最好針對所有您安裝的守護精靈都使用原生 Systemd 服務來啟動。另外,Systemd 服務可無縫用於所有使用 Systemd 的發行版,意思是 Arch 下編寫的腳本拿過來依然能夠使用。
通常來說,上游應該在發布源代碼的同時發布 Systemd 服務,但如果沒發布,你可以對照本教學來為它們寫一個並貢獻給它們。
Systemd 語法
Systemd 語法和 .desktop 文件的語法比較像,也比較類似 Windows 下的 .ini 文件,因此無論對於打包者還是最終用戶都是非常容易上手的。
主要格式請見下面的小例子,這里需要說明三點:
Systemd 單元文件中的以 「#」 開頭的行後面的內容會被認為是注釋
Systemd 下的布爾值,1、yes、on、true 都是開啟,0、no、off、false 都是關閉。註:
僅限於 Systemd 文件,比如:
RemainOnExit=yes
並不適用於該文件中嵌入的 shell 語句,比如:
ExecStartPre=/usr/bin/test "x${NETWORKMANAGER}" = xyes
這里的 yes 就不能替換。因為等號後面是一條嵌入的 shell 語句。
Systemd 下的時間單位默認是秒,所以要用毫秒(ms)分鍾(m)等請顯式說明。
一個小例子
NetworkManager 的 Systemd service:
[Unit]
Description=Network Manager
After=syslog.target
Wants=remote-fs.target network.target
[Service]
Type=dbus
BusName=org.freedesktop.NetworkManager
ExecStart=/usr/sbin/NetworkManager --no-daemon
EnvironmentFile=/etc/sysconfig/network/config
ExecStartPre=/usr/bin/test "x${NETWORKMANAGER}" = xyes
# Suppress stderr to eliminate plicated messages in syslog. NM calls openlog()
# with LOG_PERROR when run in foreground. But systemd redirects stderr to
# syslog by default, which results in logging each message twice.
StandardError=null
[Install]
WantedBy=multi-user.target
Also=NetworkManager-wait-online.service
以下我們以編寫 He.net IPv6 單元文件為例。
定義控制單元 [Unit]
在 Systemd 中,所有引導過程中 Systemd 要控制的東西都是一個單元。Systemd 單元類型有:
系統服務
套接字(socket)
設備
掛載點
自動掛載點
SWAP 文件
分區
啟動對象(startup target)
文件系統路徑
定時器
簡單說,Systemd 把 *nix 里那些分散開發因此宏觀看變成一團雜碎的東西重新統一命名了。單元名就是你寫的這個 .service 文件的名稱。但不只有 .service 後綴的文件才可以是一個單元,單元還可以有 .target, .path 等後綴,具體可以去 /usr/lib/systemd/system 下了解。但那種後綴要麼由 Systemd 上游開發者寫好隨 systemd 軟體包分發,要麼由我們的 Base:system 團隊添加,一般用戶是不太需要寫其它後綴的控制單元的。
我們先要聲明我們在定義控制單元:
[Unit]
單元名稱就不用寫了,我們要寫一條單元描述:
[Unit]
Description=Daemon to start He.net IPv6
下面我們要講解一下 Systemd 是如何控制各個單元之間的關系的。它和 RPM 的 specfile 的依賴關系控制的語法非常相似(畢竟都是紅帽一家的):
Requires: 這個單元啟動了,那麼它「需要」的單元也會被啟動; 它「需要」的單元被停止了,它自己也活不了。但是請注意,這個設定並不能控制某單元與它「需要」的單元的啟動順序(啟動順序是另外控制的),即 Systemd 不是先啟動 Requires 再啟動本單元,而是在本單元被激活時,並行啟動兩者。於是會產生爭分奪秒的問題,如果 Requires 先啟動成功,那麼皆大歡喜; 如果 Requires 啟動得慢,那本單元就會失敗(Systemd 沒有自動重試)。所以為了系統的健壯性,不建議使用這個標記,而建議使用 Wants 標記。可以使用多個 Requires。
RequiresOverridable:跟 Requires 很像。但是如果這條服務是由用戶手動啟動的,那麼 RequiresOverridable 後面的服務即使啟動不成功也不報錯。跟 Requires 比增加了一定容錯性,但是你要確定你的服務是有等待功能的。另外,如果不由用戶手動啟動而是隨系統開機啟動,那麼依然會有 Requires 面臨的問題。
Requisite:強勢版本的 Requires。要是這里需要的服務啟動不成功,那本單元文件不管能不能檢測等不能等待都立刻就會失敗。
Wants:推薦使用。本單元啟動了,它「想要」的單元也會被啟動。但是啟動不成功,對本單元沒有影響。
Conflicts:一個單元的啟動會停止與它「沖突」的單元,反之亦然。注意這里和後面的啟動順序是「正交」的:
兩個相互沖突的單元被同時啟動,要麼兩個都啟動不了(兩者都是第三個單元的 Requires),要麼啟動一個(有一個是第三個單元的 Requires,另一個不是),不是 Requires 的那個會被停止。要是兩者都不是任何一個單元的 Requires,那麼 Conflicts 別的那個單元優先啟動,被 Conflicts 的後啟動,要是互相寫了,那麼兩個都啟動不了。
OnFailure:很明顯,如果本單元失敗了,那麼啟動什麼單元作為折衷。
好了,現在我們來想像一下,我們的單元(Ipv6 隧道)應該想要什麼呢?很顯然是一個連通著的網路。有一個 Systemd 默認提供的對象叫做 network-online.target(默認的 target 列表可見 systemd.special,必看,因為你大多數時候 Wants 的都是一個固定的系統狀態而不是其它 systemd 服務),正正好好能夠提供我們需要的環境。於是:
[Unit]
Description=Daemon to start He.net IPv6
Wants=network-online.target
下面我們需要定義一下服務啟動順序,不然連 / 目錄所在的硬碟都沒掛載就開始幹活,上哪兒找程序去呀。Systemd 服務啟動順序主要使用以下兩個標記定義的:
Before/After:要是一個服務 Before 另一個服務,那麼在並行啟動時(Systemd 總是用進程 0 並行啟動所有東西,然後通過這兩個標記來二次等待排序),那另一個服務這時就會等這個服務先啟動並返回狀態,注意是先啟動而不是啟動成功,因為失敗也是一種狀態,一定要成功才啟動另一個服務是通過依賴關系定義的。反之 After 亦然。
下面說下「關機」(可以是掛起,這時候有些服務是依然在跑的,比如網路喚醒)時候的順序:如果兩個服務都是要關掉的,Before 是先關自己,After 是先關別人,這很好理解; 但如果一個服務是要關,而另一個是要開的,那麼不管 Before/After 寫了什麼,總是優先關閉而不是開始。也就是比如服務 A Before 服務 B,但是服務 B 是在關,而服務 A 是在 restart,那麼服務 B 的順序在服務 A 的前面。
好啦,我們的單元應該在什麼的前後啟動呢?它不需要一定在什麼服務前面跑起來,這不像 ifup 和 dhcp,網路起不來獲取 ip 肯定沒用。我們只需要有網就可以了。「有網」在 Systemd 中也是由一個默認 target:network.target 提供的,於是我們的控制單元就定義好了:
[Unit]
Description=Daemon to start He.net IPv6
Wants=network-online.target
After=network.target
定義服務本體 [service]
在定義完了 Systemd 用來識別服務的單元後,我們來定義服務本體,依然是聲明:
[Service]
然後是聲明服務類型:
[Service]
Type=
Systemd 支持的服務類型有以下幾類:
simple 默認,這是最簡單的服務類型。意思就是說啟動的程序就是主體程序,這個程序要是退出那麼一切皆休。這在圖形界面里非常好理解,我打開 Amarok,退出它就沒有了。但是命令行的大部分程序都不會那麼設計,因為命令行的一個最基本原則就是一個好的程序不能獨占命令行窗口。所以輸入命令,回車,接著馬上返回給你提示符,但程序已經執行了。所以只有少數程序比如 python xxx.py 還使用這種方式。在這種類型下面,如果你的主程序是要響應其它程序的,那麼你的通信頻道應該在啟動本服務前就設好(套接字等),因此這種類型的服務,Systemd 運行它後會立刻就運行下面的服務(需要它的服務),這時沒有套接字後面的服務會失敗,寫 After 也沒用,因為 simple 類型不存在主進程退出的情況也就不存在有返回狀態的情況,所以它一旦啟動就認為是成功的,除非沒起來。
forking 標准 Unix Daemon 使用的啟動方式。啟動程序後會調用 fork() 函數,把必要的通信頻道都設置好之後父進程退出,留下守護精靈的子進程。你要是使用的這種方式,最好也指定下 PIDFILE=,不要讓 Systemd 去猜,非要猜也可以,把 GuessMainPID 設為 yes。
判斷是 forking 還是 simple 類型非常簡單,命令行里運行下你的程序,持續佔用命令行要按 Ctrl + C 才可以的,就不會是 forking 類型。
創建 PIDFILE 是你為它寫服務的程序的任務而不是 Systemd 的功能,甚至也不是 Sysvinit 腳本的功能。參考 startproc創建pid file的問題了解進一步的知識。因此如果你的程序確實是 forking 類型,但就是沒實現創建 PIDFILE 的功能,那麼建議使用 ExecStartPost= 結合 shell 命令來手動抓取進程編號並寫到 /var/run/xxx.pid。
oneshot 顧名思義,打一槍換一個地方。所以這種服務類型就是啟動,完成,沒進程了。常見比如你設置網路,ifup eth0 up,就是一次性的,不存在 ifup 的子進程(forking 那樣),也不存在主進程(simple 那樣),它運行完成後便了無痕跡。因為這類服務運行完就沒進程了,我們經常會需要 RemainAfterExit=yes。後面配置的意思是說,即使沒進程了,我們也要 Systemd 認為該服務是存在並成功了的。所以如果你有一個這樣的服務,服務啟動後,你再去 ifup eth0 up,這時你再看服務,依然顯示是 running 的。因為只要在執行那條一次性命令的時候沒出錯,那麼它就永遠認為它是成功並一直存在的,直到你關閉服務。
dbus 這個程序啟動時需要獲取一塊 DBus 空間,所以需要和 BusName= 一起用。只有它成功獲得了 DBus 空間,依賴它的程序才會被啟動。
一般人也就能用到上面四個,還有兩種少見的類型:
notify 這個程序在啟動完成後會通過 sd_notify 發送一個通知消息。所以還需要配合 NotifyAccess 來讓 Systemd 接收消息,後者有三個級別:none,所有消息都忽略掉; main,只接受我們程序的主進程發過去的消息; all,我們程序的所有進程發過去的消息都算。NotifyAccess 要是不寫的話默認是 main。
idle 這個程序要等它裡面調度的全部其它東西都跑完才會跑它自己。比如你 ExecStart 的是個 shell 腳本,裡面可能跑了一些別的東西,如果不這樣的話,那很可能別的東西的控制台輸出里會多一個「啟動成功」這樣的 Systemd 消息。
由於 He.net 的 IPv6 是用 iproute2 的 ip 命令來弄的,所以是一個 oneshot 一次性服務。
[Service]
Type=oneshot
RemainAfterExit=yes
接下來要設置 ExecStart, ExecStop。如果程序支持的話,你還可以去設置 ExecReload,Restart 等。注意,這里設置的是它們 Reload/Restart 的方式,但並不代表沒有它們 Systemd 就不能完成比如 systemctl restart xxx.service 這樣的任務,程序有支持自然最好,程序不支持那就先 stop 再 start 咯。同樣有特殊要求的時候你也可以去設置比如 ExecStartPre/ExecStartPost,RestartSec,TimeoutSec 等其它東西,參考鏈接里都有使用方法。
這里要特殊講一下 ExecStart:
如果你服務的類型不是 oneshot,那麼它只可以接受一個命令,參數不限,比如你先 ip tunnel create 再 ip tunnel0 up,那是兩個 ip 命令,如果你不是 oneshot 類型這樣是不行的。
如果有多條命令(oneshot 類型),命令之間以分號 ; 分隔,跨行可用反斜杠 \。
除非你的服務類型是 forking,否則你在這里輸入的命令都會被認為是主進程,不管它是不是。
於是我們的 [Service] 就寫好了:
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/ip tunnel add he-ipv6 mode sit remote 66.220.18.42 local 108.170.7.158 ttl 255 ; \
/usr/sbin/ip link set he-ipv6 up ; \
/usr/sbin/ip addr add 2001:470:c:1184::2/64 dev he-ipv6 ; \
/usr/sbin/ip route add ::/0 dev he-ipv6 ; \
/usr/sbin/ip -6 addr
ExecStop=/usr/sbin/ip route delete ::/0 dev he-ipv6 ; \
/usr/sbin/ip -6 addr del 2001:470:c:1184::2/64 dev he-ipv6 ; \
/usr/sbin/ip link set he-ipv6 down ; \
/usr/sbin/ip tunnel del he-ipv6
安裝服務 [install]
這可能有點繞,我服務文件都弄好了,放到 /etc/systemd/system(供系統管理員和用戶使用),/usr/lib/systemd/system(供發行版打包者使用)了,不就是安裝好了嘛。
這里說的是一種內部狀態,默認你放對位置它顯示的是 disabled,unloaded,所以我們要在 Systemd 內部對它進行一下 load,沒人要的東西是不需要安裝的(我們不收渣渣),所以我們要告訴 Systemd 它是有人要的,被誰要。一般都是被
[Install]
WantedBy=multi-user.target
要(multi-user.target 表示多用戶系統好了,簡單理解就是你可以登入了)。這樣在 multi-user.target 啟用時,我們的服務也就會被啟用了。
[Install] 部分下除了 WantedBy 還有兩種屬性,分別是:
Alias= 給你自己的別名,這樣 systemctl command xxx.service 的時候就可以不輸入完整的單元名稱。比如你給 NetworkManager 一個別名叫 Alias=nm,那你就可以 systemctl status nm.service 查看實際是 NetworkManager.service 的服務了。
Also= 安裝本服務的時候還要安裝別的什麼服務。比如我們的 He.net 腳本按理應該需要一個 iproute2.service 作為 also,但是 iproute2 實際上不需要 systemd 控制,所以就沒寫。它和 [Unit] 定義裡面的依賴關系相比,它管理的不是運行時依賴,而是安裝時。安裝好了之後啟動誰先誰後,誰依賴誰,和 Also= 都沒有關系。
❽ 如何讓一個程序用system運行
其實這個都是系統system許可權都是相對的,不過可以用CreateService創建服務來實現哈!
新建一個空的,名為CreateService 控制台工程,再新建一個CreateService.cpp文件,下面代碼粘貼進去。。。
#include "Windows.h"
#include "Winsvc.h"
#include "time.h"
#include "stdio.h"
SERVICE_STATUS m_ServiceStatus;
SERVICE_STATUS_HANDLE m_ServiceStatusHandle;
BOOL bRunning=true;
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv);
void WINAPI ServiceCtrlHandler(DWORD Opcode);
BOOL InstallService();
BOOL DeleteService();
void DoTask()
{
// do something here;
}
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
// DWORD status;
// DWORD specificError;
m_ServiceStatus.dwServiceType = SERVICE_WIN32;
m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
m_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
m_ServiceStatus.dwWin32ExitCode = 0;
m_ServiceStatus.dwServiceSpecificExitCode = 0;
m_ServiceStatus.dwCheckPoint = 0;
m_ServiceStatus.dwWaitHint = 0;
//m_ServiceStatus.dwServiceType = SERVICE_AUTO_START;
m_ServiceStatusHandle = RegisterServiceCtrlHandler("Service2",ServiceCtrlHandler);
if (m_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
{
return;
}
m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
m_ServiceStatus.dwCheckPoint = 0;
m_ServiceStatus.dwWaitHint = 0;
if (!SetServiceStatus (m_ServiceStatusHandle, &m_ServiceStatus))
{
}
bRunning=true;
while(bRunning)
{
Sleep(3000);
//Place Your Code for processing here....
DoTask();
//Sleep(60*1000);
}
return;
}
void WINAPI ServiceCtrlHandler(DWORD Opcode)
{
switch(Opcode)
{
case SERVICE_CONTROL_PAUSE:
m_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
m_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
m_ServiceStatus.dwWin32ExitCode = 0;
m_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
m_ServiceStatus.dwCheckPoint = 0;
m_ServiceStatus.dwWaitHint = 0;
SetServiceStatus (m_ServiceStatusHandle,&m_ServiceStatus);
bRunning=false;
break;
case SERVICE_CONTROL_INTERROGATE:
break;
}
return;
}
BOOL InstallService()
{
char strDir[1024];
HANDLE schSCManager,schService;
GetCurrentDirectory(1024,strDir);
strcat(strDir,"\\CreateService.exe");
schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if (schSCManager == NULL)
return false;
LPCTSTR lpszBinaryPathName=strDir;
schService = CreateService((struct SC_HANDLE__ *)schSCManager,"Service2","MB Service", // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_DEMAND_START, // start type
SERVICE_ERROR_NORMAL, // error control type
lpszBinaryPathName, // service's binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // no dependencies
NULL, // LocalSystem account
NULL); // no password
if (schService == NULL)
return false;
CloseServiceHandle((struct SC_HANDLE__ *)schService);
return true;
}
BOOL DeleteService()
{
HANDLE schSCManager;
SC_HANDLE hService;
schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if (schSCManager == NULL)
return false;
hService=OpenService((struct SC_HANDLE__ *)schSCManager,"Service2",SERVICE_ALL_ACCESS);
if (hService == NULL)
return false;
if(DeleteService(hService)==0)
return false;
if(CloseServiceHandle(hService)==0)
return false;
else
return true;
}
int main(int argc, char* argv[])
{
if(argc>1)
{
if(strcmp(argv[1],"-i")==0) {
if(InstallService())
printf("\nMB Service Installed Sucessfully\n");
else
printf("\nMB Service has been installed\n");
} else if(strcmp(argv[1],"-d")==0) {
if(DeleteService())
printf("\nMB Service UnInstalled Sucessfully\n");
else
printf("\nInstalled Easin Central Service Not Found\n");
} else {
printf("\nUnknown Switch Usage\nFor Install use Servicetest -i\nFor UnInstall use Servicetest -d\n");
}
}
else
{
SERVICE_TABLE_ENTRY DispatchTable[]={{"Service2",ServiceMain},{NULL,NULL}};
StartServiceCtrlDispatcher(DispatchTable);
}
return 0;
}
成功編譯後,生成一個CreateService.exe,使用cmd-cd CreateService.exe目錄下面,輸入CreateService.exe -i 安裝服務
CreateService.exe -d 刪除服務
有點繁瑣,然後開始 - 運行 - service.msc 找到,MB Service ,右鍵啟動。
現在到任務管理器裡面去看,是不是有個CreateService.exe 【System進程的許可權】