graphviz 程序生成多種類型圖表詳解


簡介

  一幅圖抵得上千言萬語,這在描述復雜的計算機系統時尤為正確。當系統環境變得更加復雜時,用圖將它們表示出來並記入文檔就顯得更加重要。例如,虛擬化技術有很多優點,但它們通常會讓環境變得更加復雜和更難理解。Graphviz 是一個可以創建圖表的靈活應用程序,可以輕松實現腳本化。本文將介紹 Graphviz 的安裝、使用,以及其中使用 DOT 語言的基礎知識,並提供了一些示例腳本。本文有助於您了解 Graphviz 應用程序的基礎知識,以及如何編寫自動創建圖表的腳本。

  還有另外一個我覺得更加牛逼的作用,在使用 markdown 時無法直接將圖片直接粘貼上去,還得想辦法將圖片傳到某一個中間服務再引入,有么有?而 graphviz 可以完美的解決這個問題,在 markdown 中也可以直接編寫相應的代碼生成相應的圖表,使用起來相當 easy,越用越 happy。

  針對 graphviz 想要了解更加詳細內容,請查看其對對應的 官方網址

安裝 graphviz

  Graphviz 是一個開源工具,可以運行在類似於 UNIX® 的大多數平台和 Microsoft® Windows® 之上。graphviz 支持 Windows、Mac OS X、FreeBSD、Solaris、Linux 等多種系統

  •  Ubuntu 或 Debian 下安裝: 
sudo apt-get install graphviz
或
sudo yum install graphviz
  •  Mac 下安裝使用 brew 命令:

  我本人 mac 上安裝的時候並沒有裝 ruby,故需要先安裝 ruby 再進行安裝 graphviz

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" < /dev/null 2> /dev/null ; brew install caskroom/cask/brew-cask 2> /dev/null
brew install graphviz
  •  Windows 下安裝:

  由於本人一直使用的是 mac 和 linux,故此次試驗並沒有在 windows 上做驗證,請查看官方文檔進行安裝。

DOT 語言基礎

  安裝 Graphviz 之后,就可以開始使用工具創建圖表,第一步是創建一個 DOT 文件。該 DOT 文件是一個文本文件,描述了圖表的組成元素以及它們之間的關系,以便該工具可以生成這些組成元素和它們之間的關系的圖形化表示。

  1. 編寫以 dot 為后綴的源代碼文件 hello.dot,內容如下:

  digraph {
     hello -> world;
  }

   2. 使用 dot 命令編譯

  dot hello.dot -T png -o hello.png

   完整的命令格式為:

  <cmd> <inputfile> -T <format> -o <outputfile>

  其中graphviz 的 <cmd> 有好幾種,每種使用方法都完全相同,差別只在於渲染出來的圖片效果不一樣。 man 中的簡介是這樣的  

<cmd> 介紹
dot 渲染的圖具有明確方向性。
neato 渲染的圖缺乏方向性。
twopi 渲染的圖采用放射性布局。
circo 渲染的圖采用環型布局。
fdp 渲染的圖缺乏方向性。
sfdp 渲染大型的圖,圖片缺乏方向性。

  可以透過 man <cmd> 取得進一步說明。但還是親自用用比較容易理解。在本文中,凡沒有說明的圖,預設都是以 dot 渲染出來的。

  3. 查看效果

  運行 2 中的命令后會生成對應的 png 文件,雙擊打開查看效果如下所示:

    

基礎應用

1. 編寫一個案例 dot 文件為:example1.dot

graph example1 {
    Server1 -- Server2
    Server2 -- Server3
    Server3 -- Server1
}

  上述內容中共有三個節點(Server1、Server2 和 Server3)。-- 定義了節點之間的聯系。這個使用 DOT 語言的例子說明,Server2、 Server2 連接到 Server3,而 Server3 連接到 Server1。

  創建 DOT 文件后,可以運行 dot 命令來生成圖表,如 2 中所示。T png 將輸出格式指定為 PNG,而 –o example1.png 指定必須將輸出保存到一個名叫 example1.png 的文件中。

2. 從 DOT 文件生成圖像

$ dot example1.dot –T png –o example1.png

生成的圖表如下:

    

  第一個示例 (example1.dot) 描述了一個無向圖,即用不帶箭頭的直線表示節點之間的聯系的圖。

  有向圖不僅能表示節點之間的聯系,而且能用箭頭表示節點之間流動的方向。要創建有向圖,可以在 DOT 文件的第一行上指定 digraph 而非 graph,並在節點之間使用 ->,而不是 --

 3. 生成有向圖,創建 dot 文件:example2.dot

digraph example2 {
    Server1 -> Server2
    Server2 -> Server3
    Server3 -> Server1
}

 使用 dot 命令生成對應的圖表如下:

    

  你也可以輕松控制圖中每個節點的形狀、顏色和標簽。具體方法是列出每個節點的名稱,然后將選項放在名稱后面的括號中。例如,代碼行 

  Server1[shape=box, label="Server1\nWebServer", fillcolor="#ABACBA", style=filled]

  定義了 Server1 節點應該是一個長方形,有一個 Server1\nWeb Server 標簽(\n 表示一個新行),顏色設為十六進制 (hex) 顏色 #ABACBA,而且該顏色應該填充了節點。

 4. 生成有顏色和形狀的圖表

 創建 dot 文件:example3.dot

digraph example3 {
    Server1 -> Server2
    Server2 -> Server3
    Server3 -> Server1
 
    Server1 [shape=box, label="Server1\nWeb Server", fillcolor="#ABACBA", style=filled]
    Server2 [shape=triangle, label="Server2\nApp Server", fillcolor="#DDBCBC", style=filled]
    Server3 [shape=circle, label="Server3\nDatabase Server", fillcolor="#FFAA22", style=filled]
}

對應的生成相應圖表如下:

    

編寫腳本創建 Graphviz 圖表

  在了解了 Graphviz DOT 語言的基礎知識之后,您可以開始創建腳本,從而動態創建一個 DOT 文件。這允許您動態創建始終准確且保持最新的圖表。

  以下示例是一個 bash shell 腳本(hmc_to_dot.sh),它連接到 Hardware Management Console (HMC),收集托管服務器和邏輯分區 (LPAR) 的相關信息,然后使用這些信息來創建 DOT 輸出。

#!/bin/bash
 
HMC="$1"
serverlist=`ssh -q -o "BatchMode yes" $HMC lssyscfg -r sys -F "name" | sort`
 
echo "graph hmc_graph{"
for server in $serverlist; do
    echo " \"$HMC\" -- \"$server\" "
    lparlist=`ssh -q -o "BatchMode yes" $HMC lssyscfg -m $server -r lpar -F "name" | sort`
    for lpar in $lparlist; do
             echo "    \"$server\" -- \"$lpar\" "
    done
done
echo "}"

  通過提供一個 HMC 服務器名稱作為參數傳遞給腳本,便可運行此腳本。該腳本將傳遞的第一個參數設置為 $HMC 變量。設置 $serverlist 變量的方法是連接到 HMC 並獲得該 HMC 控制的所有托管服務器的清單。在這些托管服務器上進行循環,而腳本將為每台托管服務器打印一行 "HMC" -- "server" ,這表明 Graphviz 在每台 HMC 與其托管服務器之間繪制了一條直線。此外針對每台托管服務器,腳本再次連接到 HMC 並獲得該托管系統上的 LPAR 清單,然后通過它們循環打印一行 "server" -- "LPAR"。這表明 Graphviz 在每台托管服務器與其 LPAR 之間都繪制了一條直線。(此腳本要求您在運行腳本的服務器與 HMC 之間設置 Secure Shell (SSH) 密鑰身份驗證)。

命令執行如下:

  ./hmc_to_dot.sh hmc_name

以上執行對應輸出的內容如下所示:

graph hmc_graph{
    "hmc01" -- "test520"
        "test520" -- "lpar2"
        "test520" -- "lpar3"
    "hmc01" -- "test570"
        "test570" -- "aixtest01"
        "test570" -- "aixtest02"
        "test570" -- "aixtest03"
    "hmc01" -- "test510"
        "test510" -- "lpar1"
}

 你可以輕松從腳本生成圖,具體方法是運行以下命令:

./hmc_to_dot.sh hmc_server_name | dot -T png -o hmc_graph.png

 運行腳本,該腳本會動態創建 DOT 語言,然后將這些輸出傳遞給 dot 命令,以便讓它創建一個文件名為 hmc_graph.png 的圖表。下圖顯示了創建的圖表。

     

基礎語法總結(供有識之士參考)

具體的圖說明內容包含屬性(attr)、節點(node)、邊(edge)和子圖(subgraph)說明。

節點屬性如下 :

Name Default Values
color black node shape color
comment   any string (format-dependent)
distortion 0.0 node distortion for shape=polygon
fillcolor lightgrey/black node fill color
fixedsize false label text has no affect on node size
fontcolor black type face color
fontname Times-Roman font family
fontsize 14 point size of label
group   name of node’s group
height .5 height in inches
label node name any string
layer overlay range all, id or id:id
orientation 0.0 node rotation angle
peripheries shape-dependent number of node boundaries
regular false force polygon to be regular
shape ellipse node shape; see Section 2.1 and Appendix E
shapefile   external EPSF or SVG custom shape file
sides 4 number of sides for shape=polygon
skew 0.0 skewing of node for shape=polygon
style   graphics options, e.g. bold, dotted, filled; cf. Section 2.3
URL   URL associated with node (format-dependent)
width .75 width in inches
z 0.0 z coordinate for VRML output

邊框屬性:

Name Default Values
arrowhead normal style of arrowhead at head end
arrowsize 1.0 scaling factor for arrowheads
arrowtail normal style of arrowhead at tail end
color black edge stroke color
comment   any string (format-dependent)
constraint true use edge to affect node ranking
decorate   if set, draws a line connecting labels with their edges
dir forward forward, back, both, or none
fontcolor black type face color
fontname Times-Roman font family
fontsize 14 point size of label
headlabel   label placed near head of edge
headport   n,ne,e,se,s,sw,w,nw
headURL   URL attached to head label if output format is ismap
label   edge label
labelangle -25.0 angle in degrees which head or tail label is rotated off edge
labeldistance 1.0 scaling factor for distance of head or tail label from node
labelfloat false lessen constraints on edge label placement
labelfontcolor black type face color for head and tail labels
labelfontname Times-Roman font family for head and tail labels
labelfontsize 14 point size for head and tail labels
layer overlay range all, id or id:id
lhead   name of cluster to use as head of edge
ltail   name of cluster to use as tail of edge
minlen 1 minimum rank distance between head and tail
samehead   tag for head node; edge heads with the same tag are
sametail   merged onto the same port
style   tag for tail node; edge tails with the same tag are merged onto the same port
taillabel   graphics options, e.g. bold, dotted, filled; cf. Section 2.3
tailport   label placed near tail of edge n,ne,e,se,s,sw,w,nw
tailURL   URL attached to tail label if output format is ismap
weight 1 integer cost of stretching an edge

圖屬性如下:

Name Default Values
bgcolor   background color for drawing, plus initial fill color
center false center drawing on page
clusterrank local may be global or none
color black for clusters, outline color, and fill color if fillcolor not defined
comment   any string (format-dependent)
compound false allow edges between clusters
concentrate false enables edge concentrators
fillcolor black cluster fill color
fontcolor black type face color
fontname Times-Roman font family
fontpath   list of directories to search for fonts
fontsize 14 point size of label
label   any string
labeljust centered ”l” and ”r” for left- and right-justified cluster labels, respectively
labelloc top ”t” and ”b” for top- and bottom-justified cluster labels, respectively
layers   id:id:id…
margin .5 margin included in page, inches
mclimit 1.0 scale factor for mincross iterations
nodesep .25 separation between nodes, in inches.
nslimit   if set to f, bounds network simplex iterations by (f)(number of nodes) when setting x-coordinates
nslimit1   if set to f, bounds network simplex iterations by (f)(number of nodes) when ranking nodes
ordering   if out out edge order is preserved
orientation portrait if rotate is not used and the value is landscape, use landscape orientation
page   unit of pagination, e.g. “8.5,11”
pagedir BL traversal order of pages
quantum   if quantum ¿ 0.0, node label dimensions will be rounded to integral multiples of quantum
rank   same, min, max, source or sink
rankdir TB LR (left to right) or TB (top to bottom)
ranksep .75 separation between ranks, in inches.
ratio   approximate aspect ratio desired, fill or auto
remincross   if true and there are multiple clusters, re-run crossing minimization
rotate   If 90, set orientation to landscape
samplepoints 8 number of points used to represent ellipses and circles on output (cf. Appendix C
searchsize 30 maximum edges with negative cut values to check when looking for a minimum one during network simplex
size   maximum drawing size, in inches
style   graphics options, e.g. filled for clusters
URL   URL associated with graph (format-dependent)

具體實例

  這里列舉幾個常用到的例子,還有更加詳細的例子還可以參考 官網例子中心

 下面是一個二叉樹代碼:

digraph g {
    node [shape = record,height=.1];
    node0[label = "<f0> |<f1> G|<f2> "];
    node1[label = "<f0> |<f1> E|<f2> "];
    node2[label = "<f0> |<f1> B|<f2> "];
    node3[label = "<f0> |<f1> F|<f2> "];
    node4[label = "<f0> |<f1> R|<f2> "];
    node5[label = "<f0> |<f1> H|<f2> "];
    node6[label = "<f0> |<f1> Y|<f2> "];
    node7[label = "<f0> |<f1> A|<f2> "];
    node8[label = "<f0> |<f1> C|<f2> "];
    "node0":f2 -> "node4":f1;
    "node0":f0 -> "node1":f1;
    "node1":f0 -> "node2":f1;
    "node1":f2 -> "node3":f1;
    "node2":f2 -> "node8":f1;
    "node2":f0 -> "node7":f1;
    "node4":f2 -> "node6":f1;
    "node4":f0 -> "node5":f1;
}

    

python 調用

  除了可以使用 dot 文件編寫圖形外,也可以使用python編寫相關的代碼,生成圖形文件, 安裝 python 對應的 graphviz 相應的模塊

  pip install pygraphviz

   引用 pygraphviz

  import pygraphviz as pgv

   初始化圖類

  G = pgv.AGraph()

   增加節點和邊

  G.add_node('a')       # adds node 'a'
  G.add_edge('b','c')   # adds edge 'b'-'c' (and also nodes 'b', 'c')

  設置屬性

  G.graph_attr['label'] = 'test graphf'
  G.node_attr['shape'] = 'circle'
  G.edge_attr['color'] = 'red'

   設置輸出的格式

  G.layout()              # default to neato
  G.layout(prog='dot')    # use do

   輸出到文件

  G.draw('file.png')              # write previously positioned graph to PNG file
  G.draw('file.ps',prog='circo')  # use circo to position, write PS file

   效果如下圖所示:

    

結束語

  由於當今的動態虛擬環境的存在,系統在不斷變化,很難保持文檔與圖表的時效性和准確性。本文介紹了 Graphviz 的基礎知識,以及如何通過編寫腳本,利用 Graphviz 的強大功能來創建最新、最准確的自動化環境圖表。您可以從 cron 運行這些腳本,並將圖表放在 Web 服務器上,這樣就可以在您需要時隨時重新創建圖表,並通過 Web 瀏覽器輕松訪問它們。

總結使用案例

案例一:

digraph startgame {
    label="游戲資源更新流程"
    rankdir="TB"
    start[label="啟動游戲" shape=circle style=filled]
    ifwifi[label="網絡環境判斷是否 WIFI" shape=diamond]
    needupdate[label="是否有資源需要更新" shape=diamond]
    startslientdl[label="靜默下載" shape=box]
    enterhall[label="進入游戲大廳" shape=box]

    enterroom[label="進入房間" shape=box]
    resourceuptodate[label="資源不完整" shape=diamond]
    startplay[label="正常游戲" shape=circle fillcolor=blue]
    warning[label="提醒玩家是否更新" shape=diamond]
    startdl[label="進入下載界面" shape=box]
    //{rank=same; needupdate, enterhall}

    {shape=diamond; ifwifi, needupdate}

    start -> ifwifi
    ifwifi->needupdate[label="是"]
    ifwifi->enterhall[label="否"]
    needupdate->startslientdl[label="是"]
    startslientdl->enterhall
    needupdate->enterhall[label="否"]

    enterhall -> enterroom
    enterroom -> resourceuptodate
    resourceuptodate -> warning[label="是"]
    resourceuptodate -> startplay[label="否"]
    warning -> startdl[label="確認下載"]
    warning -> enterhall[label="取消下載"]
    startdl -> enterhall[label="取消下載"]
    startdl -> startplay[label="下載完成"]
}

        

案例二:

digraph G{

    size = "5, 5";//圖片大小
    main[shape=box];/*形狀*/

    main->parse;
    parse->execute;

    main->init[style = dotted];//虛線

    main->cleanup;
    edge[color = green]; // 連接線的顏色

    execute->{make_string; printf}//連接兩個

    init->make_string;
    main->printf[style=bold, label="100 times"];//線的 label

    make_string[label = "make a\nstring"]// \n, 這個node的label,注意和上一行的區別

    node[shape = box, style = filled, color = ".7.3 1.0"];//一個node的屬性

    execute->compare;
}

        

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM