热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

AI学习—TensorFlow框架介绍[图+会话+张量+变量OP+API]

   TensorFlow的数据流图TensorFlow的结构分析:图+会话    TensorFlow构图阶段(数据与操作的执行步骤被描绘出一个图)+执行图阶段(使用回

image

image   

image


TensorFlow的数据流图



  • TensorFlow的结构分析: 图 + 会话

     TensorFlow = 构图阶段(数据与操作的执行步骤被描绘出一个图) + 执行图阶段(使用回话执行构建好的图中操作)

        1. 一个构建图阶段
              流程图:定义数据(张量Tensor)和操作(节点Operate)
        2. 一个执行图阶段
              调用各方资源,将定义好的数据和操作运行起来

image

 



  • 数据流图介绍

      数据流图【Data Flow Graph】用“结点”(nodes)和“线”(edges)的有向图来描述数学计算。“节点” 一般用来表示施加的数学操作,但也可以表示数据输入(feed in)的起点/输出(push out)的终点,或者是读取/写入持久变量(persistent variable)的终点。“线”表示“节点”之间的输入/输出关系。这些数据“线”可以输运“size可动态调整”的多维数据数组,即“张量”(tensor)。张量从图中流过的直观图像是这个工具取名为“Tensorflow”的原因。一旦输入端的所有张量准备好,节点将被分配到各种计算设备完成异步并行地执行运算。

image      tensors_flowing

简单计算的Demo:用于区别py和TF的区别:

import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # 取消TF对我们的一些提示
def tensorflow_demo():
"""
TensorFlow的基本结构
:return:
"""
# 原生python加法运算
a = 2
b = 3
c = a + b
print("普通加法运算的结果:\n", c)
# TensorFlow实现加法运算,可以理解为我们定义了一个图
a_t = tf.constant(2) # 这里是我们的张量
b_t = tf.constant(3) # 这里是我们的张量
c_t = a_t + b_t # 定义了节点
print("TensorFlow加法运算的结果:\n", c_t)
# TF必须先开启会话,可以理解回话调用CPU资源进行计算
with tf.Session() as sess:
c_t_value = sess.run(c_t)
print("c_t_value:\n", c_t_value)
return None
if __name__ == "__main__":
tensorflow_demo()

image

 

问题定位:

    解决ImportError: numpy.core.multiarray failed to import

问题解决:

    pip install -U numpy


图与TensorBoard

    图包含了一组tf.Operation代表的计算单元对象和tf.Tensor代表的计算单元直接流动的数据。



  • 图的相关操作(默认图 + 自定义图)
        1 默认图
            查看默认图的方法
                1)调用方法
                    用tf.get_default_graph()
                2)查看属性
                    with tf.Session() as sess:
                          tt = sess.graph

import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # 取消TF对我们的一些提示
def graph_demo():
a_t = tf.constant(2)
b_t = tf.constant(3)
c_t = tf.add(a_t, b_t)
print("TensorFlow加法运算的结果:\n", c_t)
'''
查看默认图:
1. 调用get_default_graph()
2. session.graph
'''
# 方法1-1:调用默认方法
default_g = tf.get_default_graph()
print('调用get_default_graph: \n', default_g)
# 方法2-1:查看张量属性
print("a_t的图属性:\n", a_t.graph)
print("c_t的图属性:\n", c_t.graph)
# 方法2-2:查看回话属性
with tf.Session() as sess:
session_g = sess.graph
print("回话属性:", session_g)
new_c_t = sess.run(c_t)
print("TensorFlow回话的的结果c_t_value:\n", new_c_t)
if __name__ == "__main__":
graph_demo()

image

        2 创建图
             new_g = tf.Graph()  # 自定义一个图
             with new_g.as_default():
                   定义数据和操作

             with tf.Session(graph=new_g) as sess:    # 如果不添加graph=new_g,默认调用默认的图,而不是我们自定义的图

                    sess.run(XXX)

import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # 取消TF对我们的一些提示
def graph_demo():
# 第一步:自定义图
new_g = tf.Graph()
# 第二步:在自己的图中定义数据和操作
with new_g.as_default():
a_new = tf.constant(20)
b_new = tf.constant(30)
c_new = a_new + b_new
print("a_new:\n", a_new)
print("b_new:\n", b_new)
print("c_new:\n", c_new)
print("a_new的图属性:\n", a_new.graph)
print("c_new的图属性:\n", c_new.graph)
# 开启new_g的会话,即开启了一个上下文管理器
with tf.Session(graph=new_g) as new_sess:
c_new_value = new_sess.run((c_new))
print("c_new_value:\n", c_new_value)
print("new_sess的图属性:\n", new_sess.graph)
return None
if __name__ == "__main__":
graph_demo()

image

 

TF有一个亮点就是我们自己写的程序可以进行可视化,这个就是TensorBoard。


Tensorboard的介绍

image

TensorBoard:可视化学习: 数字序列化 + 启动Tensorboard
    1 数据序列化(即events文件)  (因为图也是一个对象,不能以编码的形式写在本地,需要序列化,序列化后的文件叫做events)
        tf.summary.FileWriter(path, graph=sess.graph)
    2 tensorboard

imageimage

import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # 取消TF对我们的一些提示
def graph_demo():
"""
自定义图的演示 + Tensorboard可视化
:return:
"""
# 自定义图
new_g = tf.Graph()
# 在自己的图中定义数据和操作
with new_g.as_default():
a_new = tf.constant(20)
b_new = tf.constant(30)
c_new = a_new + b_new
print("a_new:\n", a_new)
print("b_new:\n", b_new)
print("c_new:\n", c_new)
print("a_new的图属性:\n", a_new.graph)
print("c_new的图属性:\n", c_new.graph)
# 开启new_g的会话
with tf.Session(graph=new_g) as new_sess:
c_new_value = new_sess.run((c_new))
print("c_new_value:\n", c_new_value)
print("new_sess的图属性:\n", new_sess.graph)
# 1)将图写入本地生成events文件
tf.summary.FileWriter("./summary", graph=new_sess.graph)
return None
if __name__ == "__main__":
graph_demo()

2) 可视化:

      如果没有添加环境变量,就需要进入的Tensorboard的安装目录下进行终端操作

image

代码输出结果:

image

可视化结果:

http://ftl2018:6006/#graphs&run=.   火狐浏览器打开

image

下面我们讲究OP对象


Operation的介绍

    一个图我们包含数据(Tensor对象) + 操作(Operation对象)

       1 常见OP(操作函数和操作对象联系与区别)
                      操作函数                          &                           操作对象
           tf.constant(Tensor对象)                 |   输入Tensor对象 –> Const对象 –> 输出 Tensor对象
           tf.add(Tensor对象1, Tensor对象2)    |   输入Tensor对象1, Tensor对象2 - Add对象 - 输出 Tensor对象3

        说明:

假设我们定义了a_new = tf.constant(20);

这里我们定义的数字20也是一个Tensor对象,数字20传递给了tf.constant()函数(即操作函数),然后生成一个Const对象(即操作对象,这里只是一个数字定义,如果进行add()求和,则是Add对象), 到最后我们拿到的也是一个Tensor对象。

       2 指令名称
          同一张图,有且只有一个命名唯一空间,默认是递增,Const_0,Const_1,当然我们也可以自定义名称

a_t = tf.constant(2) # 默认的name都是Const
b_t = tf.constant(3, name="a_t")

image



  • 常见的OP

image

我们打印出来的实际上都是数值(张量值,且OP指令都唯一)。下图是sum_c: 就是由add这个操作产生的

image



  • 指令名称

image


会话

会话(Session+InteractiveSession)
    1、tf.Session:用于完整的程序当中
    2、tf.InteractiveSession:用于交互式上下文中的TensorFlow ,例如shell,我们打开一个回话,可以利用a.eval()进行快速取值
            3 feed操作
        a = tf.placeholder(tf.float32, shape=)
        b = tf.placeholder(tf.float32, shape=)  

image

会话的关键API说明



  •   关于初始化__init__()函数:

        1)会话掌握资源,用完要回收 - 上下文管理器

with tf.Session(graph=new_g) as new_sess:

        2)初始化会话对象时的参数

def __init__(self, target='', graph=None, cOnfig=None):

            graph=None,默认运行我们的默认图
            target:如果将此参数留空(默认设置), 会话将仅使用本地计算机中的设备。
                       可以指定 grpc:// 网址,以便指定远程TensorFlow 服务器的地址,
                       这使得会话可以访问该服务器控制的计算机上的所有设备。
            config:此参数允许您指定一个 tf.ConfigProto以便控制会话的行为。例如,ConfigProto协议用于打印设备使用信息

        3)run(fetches,feed_dict=None)

def run(self, fetches, feed_dict=None, optiOns=None, run_metadata=None):

              fetches:单一的operation,或者列表、元组(不属于TensorFlow的不行)

              feed_ditc: 允许调用者覆盖图中张量的值,运行时赋值

                      --》一般与 a = tf.placeholder(tf.float32, shape=)(提供占位符)搭配使用,则会检查值的形状是否与占位符兼容
 

import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
def session_demo():
"""
会话的演示
:return:
"""
info1 = '''
============fetches参数传================
'''
print(info1)
# TensorFlow实现加法运算
a_t = tf.constant(2, name="a_t")
b_t = tf.constant(3, name="a_t")
c_t = tf.add(a_t, b_t, name="c_t")
print("a_t:\n", a_t)
print("b_t:\n", b_t)
print("c_t:\n", c_t)
# print("c_t.eval():\n", c_t.eval())
# 开启会话
with tf.Session(cOnfig=tf.ConfigProto(allow_soft_placement=True,
log_device_placement=True)) as sess:
'''
# fetches参数传递多个值demo:
1. abc = sess.run(fetches=[a_t, b_t, c_t]) 返回的值也是一个列表格式
2. a, b, c sess.run([a_t, b_t, c_t]) 用a,b,c分别接受列表的值
'''
# fetches参数传递单一demo:
c_new_value = sess.run(c_t)
print('session.run()执行结果:\n', c_new_value)
print("c_t_value:\n", c_t.eval())
print("sess的图属性:\n", sess.graph)
info = '''
============feed的Demo================
'''
print(info)
# 定义占位符
a_ph = tf.placeholder(tf.float32) # 这里占位的个浮点型,所以下面传递一个浮点型数据
b_ph = tf.placeholder(tf.float32)
c_ph = tf.add(a_ph, b_ph)
print("a_ph:\n", a_ph)
print("b_ph:\n", b_ph)
print("c_ph:\n", c_ph)
# 开启会话
with tf.Session(cOnfig=tf.ConfigProto(allow_soft_placement=True,
log_device_placement=True)) as session:
c_ph_value = session.run(c_ph, feed_dict={a_ph: 3.9, b_ph: 4.8})
print("占位符:c_ph_value:\n", c_ph_value)
if __name__ == "__main__":
session_demo()

image


张量的介绍

  TensorFlow的张量就是一个n维数组,类型为tf.Tensor。类似于我们见过的ndarray.

           --> 2个重要的属性(type + shape)

                  1. 数据类型(type)

                  2. 形状(阶)shape
计算机中各个变量的存储情况:

        标量 一个数字                   0阶张量
        向量 一维数组 [2, 3, 4]       1阶张量
        矩阵 二维数组 [[2, 3, 4],     2阶张量
                    [2, 3, 4]]
        ……
        张量 n维数组                      n阶张量



  • 张量的类型

image



  • 张量的阶

image

import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
def tensor_demo():
'''
张量的demo
:return:
'''

'''
创建张量的时候,如果不指定类型
默 认 tf.float32
整 型 tf.int32
浮点型 tf.float32
'''
tensor1 = tf.constant(4.0) # 显示空的元组(),没有指定数组类型
tensor2 = tf.constant([1, 2, 3, 4]) # 显示一个一位数组,表示成(4,)
linear_squares = tf.constant([[4], [9], [16], [25]], dtype=tf.int32) # 显示一个二维数组,表示成(4,1),4行一列
print("tensor1:\n", tensor1) # Tensor("Const:0", shape=(), dtype=float32)
print("tensor2:\n", tensor2) # Tensor("Const_1:0", shape=(4,), dtype=int32)
print("linear_squares_before:\n", linear_squares) # Tensor("Const_2:0", shape=(4, 1), dtype=int32)
if __name__ == "__main__":
tensor_demo()

image

  创建张量的指令

       张量的指令 = 固定值张量 + 随机张量



  • 创建固定的张量

image

demo:

import tensorflow as tf
tf.zeros(shape=[3,4]).eval()
tf.ones(shape=[3,4]).eval()

image



  • 创建随机张量

image

import tensorflow as tf
# 创建3行4列的数组,均值为1.75,标准差为2
tf.random_normal(shape=[3,4], mean=1.75, stddev=2)
# # 创建3行4列的数组,均值为1.75,标准差为2,通过eval()查看具体的值
tf.random_normal(shape=[3,4], mean=1.75, stddev=2).eval()

image



  • 张量的修改(类型+形状)与运算


复习ndarray属性的修改
    类型的修改
        1)ndarray.astype(type)
        2)ndarray转换为编码格式:ndarray.tostring()
    形状的修改
        1)ndarray.reshape(shape)
             自动计算形状:ndarray.reshape(-1)
        2)ndarray.resize(shape)
        说明:reshape会返回一个新的数组,resize会就地修改


1、类型改变


tf.cast(tensor, dtype)
    不会改变原始的tensor
    返回新的改变类型后的tensor


image

2、形状改变(静态形状+动态形状)


    静态形状 - 初始创建张量时的形状
        1)如何改变静态形状
            tensor.set_shape(shape)
                问:什么情况下才可以改变/更新静态形状?
                答:只有在形状没有完全固定下来(也就是?的部分)的情况下
           
        2)如何改变动态形状
            tf.reshape(tensor, shape)
            不会改变原始的tensor
            返回新的改变形状后的tensor
            动态创建新张量时,张量的元素个数必须匹配(可跨阶,但是数量必须一致)


  image

demo:

import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
def tensor_demo():
'''
张量类型修改
:return:
'''
'''
创建张量的时候,如果不指定类型
默 认 tf.float32
整 型 tf.int32
浮点型 tf.float32
'''
tensor1 = tf.constant(4.0) # 显示空的元组(),没有指定数组类型
tensor2 = tf.constant([1, 2, 3, 4]) # 显示一个一维有4个元素的数组,表示成(4,)
linear_squares = tf.constant([[4], [9], [16], [25]], dtype=tf.int32) # 显示一个二维数组,表示成(4,1),4行一列
print("tensor1:\n", tensor1) # Tensor("Const:0", shape=(), dtype=float32)
print("tensor2:\n", tensor2) # Tensor("Const_1:0", shape=(4,), dtype=int32)
print("linear_squares_before:\n", linear_squares) # Tensor("Const_2:0", shape=(4, 1), dtype=int32)
'''
张量类型的修改:
不会改变原始的tensor
返回新的改变类型后的tensor
'''
l_cast = tf.cast(linear_squares, dtype=tf.float32)
print("linear_squares_after:\n", linear_squares)
print("l_cast:\n", l_cast)
'''
张量形状的改变:
# 更新/改变静态形状
# 定义占位符
'''
# a_p,b_p是没有完全固定下来的静态形状,但是形状以及是二维了,只能传递2维的数组
a_p = tf.placeholder(dtype=tf.float32, shape=[None, None]) # a_PTensor("Placeholder:0", shape=(?, ?), dtype=float32)
b_p = tf.placeholder(dtype=tf.float32, shape=[None, 10]) # b_p维度是2维,但是有10列已经确定了,不能更改
# c_p是2维且形状以及固定,不能随便更改
c_p = tf.placeholder(dtype=tf.float32, shape=[3, 2]) #
print("a_p:\n", a_p)
print("b_p:\n", b_p)
print("c_p:\n", c_p)
# 更新形状未确定的部分
# a_p.set_shape([2, 3]) # a_p.set_shape([2, 3, 3])报错,二维不兼容三维
# b_p.set_shape([2, 10])
# c_p.set_shape([3, 2]) # 单行执行会报错,both shapes must be equal,
'''
张量形状的改变:
# 动态形状修改,如果确定了元素数量,则可以修改元素的阶,但是不能修改总量
例如:
shape=[2,3] ==> shape=[2,3,1] # 正确,元素数量未变化
shape=[2,3] ==> shape=[3,2] # 正确,元素数量未变化
shape=[2,3] ==> shape=[3,3] # 错误,元素数量变化了,改变后是9个
'''
a_p_reshape = tf.reshape(a_p, shape=[2, 3, 1])
print("a_p:\n", a_p)
# print("b_p:\n", b_p)
print("a_p_reshape:\n", a_p_reshape)
c_p_reshape = tf.reshape(c_p, shape=[2, 3])
print("c_p:\n", c_p)
print("c_p_reshape:\n", c_p_reshape)
if __name__ == "__main__":
tensor_demo()

image



  • 张量的数学运算

image

可参考官网:(需FQ)

image

image


变量OP的介绍

TensorFlow - 变量很适合于存储模型参数

image



  • 创建变量(需要显示初始化以后才可以完成变量初始化)

image



  • 使用tf.variable_scope()修改变量的命名空间

   添加命名空间后,使得结构更加清晰

image

demo:

import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
def variable_demo():
"""
变量的演示
:return:
"""
'''
# 创建变量:没有开启会话之前的demo:
'''
aa = tf.Variable(initial_value=50) #
bb = tf.Variable(initial_value=50) #
cc = tf.add(aa, bb) # Tensor("Add:0", shape=(), dtype=int32)
print("aa:\n", aa)
print("bb:\n", bb)
print("cc:\n", cc)
'''
# 创建变量: 开启会话的demo:
'''
with tf.variable_scope("my_scope"):
a = tf.Variable(initial_value=50)
b = tf.Variable(initial_value=40)
with tf.variable_scope("your_scope"): # 修改变量的命名空间
c = tf.add(a, b)
print("a:\n", a)
print("b:\n", b)
print("c:\n", c)
# 初始化变量
# a = tf.Variable(initial_value=50)这正是一个初始化的值,而并非变量的初始化
init = tf.global_variables_initializer()
# 开启会话
with tf.Session() as sess:
# 给全局的变量做了初始化
sess.run(init)
a_value, b_value, c_value = sess.run([a, b, c])
print("a_value:\n", a_value)
print("b_value:\n", b_value)
print("c_value:\n", c_value)
return None
if __name__ == "__main__":
variable_demo()

image

 


基础API和高级API



  • 基础API

image

image



  • 高级API

image



  • 关于TensorFlow的API图示

image

作者:小a玖拾柒

出处:http://www.cnblogs.com/ftl1012/

-------------------------------------------

个性签名: 所有的事情到最後都是好的,如果不好,那說明事情還沒有到最後~

本文版权归作者【小a玖拾柒】和【博客园】共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利!



推荐阅读
  • 通过Anaconda安装tensorflow,并安装运行spyder编译器的完整教程
    本文提供了一个完整的教程,介绍了如何通过Anaconda安装tensorflow,并安装运行spyder编译器。文章详细介绍了安装Anaconda、创建tensorflow环境、安装GPU版本tensorflow、安装和运行Spyder编译器以及安装OpenCV等步骤。该教程适用于Windows 8操作系统,并提供了相关的网址供参考。通过本教程,读者可以轻松地安装和配置tensorflow环境,以及运行spyder编译器进行开发。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 安装mysqlclient失败解决办法
    本文介绍了在MAC系统中,使用django使用mysql数据库报错的解决办法。通过源码安装mysqlclient或将mysql_config添加到系统环境变量中,可以解决安装mysqlclient失败的问题。同时,还介绍了查看mysql安装路径和使配置文件生效的方法。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • HDFS2.x新特性
    一、集群间数据拷贝scp实现两个远程主机之间的文件复制scp-rhello.txtroothadoop103:useratguiguhello.txt推pushscp-rr ... [详细]
  • 31.项目部署
    目录1一些概念1.1项目部署1.2WSGI1.3uWSGI1.4Nginx2安装环境与迁移项目2.1项目内容2.2项目配置2.2.1DEBUG2.2.2STAT ... [详细]
  • 本文介绍了Composer依赖管理的重要性及使用方法。对于现代语言而言,包管理器是标配,而Composer作为PHP的包管理器,解决了PEAR的问题,并且使用简单,方便提交自己的包。文章还提到了使用Composer能够避免各种include的问题,避免命名空间冲突,并且能够方便地安装升级扩展包。 ... [详细]
  • EzPP 0.2发布,新增YAML布局渲染功能
    EzPP发布了0.2.1版本,新增了YAML布局渲染功能,可以将YAML文件渲染为图片,并且可以复用YAML作为模版,通过传递不同参数生成不同的图片。这个功能可以用于绘制Logo、封面或其他图片,让用户不需要安装或卸载Photoshop。文章还提供了一个入门例子,介绍了使用ezpp的基本渲染方法,以及如何使用canvas、text类元素、自定义字体等。 ... [详细]
  • 本文介绍了在Python张量流中使用make_merged_spec()方法合并设备规格对象的方法和语法,以及参数和返回值的说明,并提供了一个示例代码。 ... [详细]
  • MySQL数据库锁机制及其应用(数据库锁的概念)
    本文介绍了MySQL数据库锁机制及其应用。数据库锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,数据是一种供许多用户共享的资源,如何保证数据并发访问的一致性和有效性是数据库必须解决的问题。MySQL的锁机制相对简单,不同的存储引擎支持不同的锁机制,主要包括表级锁、行级锁和页面锁。本文详细介绍了MySQL表级锁的锁模式和特点,以及行级锁和页面锁的特点和应用场景。同时还讨论了锁冲突对数据库并发访问性能的影响。 ... [详细]
  • 本文总结了使用不同方式生成 Dataframe 的方法,包括通过CSV文件、Excel文件、python dictionary、List of tuples和List of dictionary。同时介绍了一些注意事项,如使用绝对路径引入文件和安装xlrd包来读取Excel文件。 ... [详细]
  • AFNetwork框架(零)使用NSURLSession进行网络请求
    本文介绍了AFNetwork框架中使用NSURLSession进行网络请求的方法,包括NSURLSession的配置、请求的创建和执行等步骤。同时还介绍了NSURLSessionDelegate和NSURLSessionConfiguration的相关内容。通过本文可以了解到AFNetwork框架中使用NSURLSession进行网络请求的基本流程和注意事项。 ... [详细]
  • Python已成为全球最受欢迎的编程语言之一,然而Python程序的安全运行存在一定的风险。本文介绍了Python程序安全运行需要满足的三个条件,即系统路径上的每个条目都处于安全的位置、"主脚本"所在的目录始终位于系统路径中、若python命令使用-c和-m选项,调用程序的目录也必须是安全的。同时,文章还提出了一些预防措施,如避免将下载文件夹作为当前工作目录、使用pip所在路径而不是直接使用python命令等。对于初学Python的读者来说,这些内容将有所帮助。 ... [详细]
  • 安装oracle软件1创建用户组、用户和目录bjdb节点下:[rootnode1]#groupadd-g200oinstall[rootnode1]#groupad ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有