2018年4月

前面的文章 中,我们学习了在 Linux、macOS、以及 Windows 上如何使用 Docker 的基础知识。在这篇文章中,我们将学习创建 Docker 镜像的基本知识。我们可以在 DockerHub 上得到可用于你自己的项目的预构建镜像,并且也可以将你自己的镜像发布到这里。

我们使用预构建镜像得到一个基本的 Linux 子系统,因为,从头开始构建需要大量的工作。你可以使用 Alpine( Docker 版使用的官方版本)、Ubuntu、BusyBox、或者 scratch。在我们的示例中,我将使用 Ubuntu。

在我们开始构建镜像之前,让我们先“容器化”它们!我的意思是,为你的所有 Docker 镜像创建目录,这样你就可以维护不同的项目和阶段,并保持它们彼此隔离。

$ mkdir dockerprojects
cd dockerprojects

现在,在 dockerprojects 目录中,你可以使用自己喜欢的文本编辑器去创建一个 Dockerfile 文件;我喜欢使用 nano,它对新手来说很容易上手。

$ nano Dockerfile

然后添加这样的一行内容:

FROM Ubuntu

使用 Ctrl+Exit 然后选择 Y 去保存它。

现在开始创建你的新镜像,然后给它起一个名字(在刚才的目录中运行如下的命令):

$ docker build -t dockp .

(注意命令后面的圆点)这样就创建成功了,因此,你将看到如下内容:

Sending build context to Docker daemon  2.048kB
Step 1/1 : FROM ubuntu
---> 2a4cca5ac898
Successfully built 2a4cca5ac898
Successfully tagged dockp:latest

现在去运行和测试一下你的镜像:

$ docker run -it Ubuntu

你将看到 root 提示符:

root@c06fcd6af0e8:/#

这意味着在 Linux、Windows、或者 macOS 中你可以运行一个最小的 Ubuntu 了。你可以运行所有的 Ubuntu 原生命令或者 CLI 实用程序。

我们来查看一下在你的目录下你拥有的所有 Docker 镜像:

$docker images

REPOSITORY TAG IMAGE ID CREATED SIZE
dockp latest 2a4cca5ac898 1 hour ago 111MB
ubuntu latest 2a4cca5ac898 1 hour ago 111MB
hello-world latest f2a91732366c 8 weeks ago 1.85kB

你可以看到共有三个镜像:dockpUbuntu、和 hello-worldhello-world 是我在几周前创建的,这一系列的前面的文章就是在它下面工作的。构建一个完整的 LAMP 栈可能是一个挑战,因此,我们使用 Dockerfile 去创建一个简单的 Apache 服务器镜像。

从本质上说,Dockerfile 是安装所有需要的包、配置、以及拷贝文件的一套指令。在这个案例中,它是安装配置 Apache 和 Nginx。

你也可以在 DockerHub 上去创建一个帐户,然后在构建镜像之前登入到你的帐户,在这个案例中,你需要从 DockerHub 上拉取一些东西。从命令行中登入 DockerHub,运行如下所求的命令:

$ docker login

在登入时输入你的用户名和密码。

接下来,为这个 Docker 项目,在目录中创建一个 Apache 目录:

$ mkdir apache

在 Apache 目录中创建 Dockerfile 文件:

$ nano Dockerfile

然后,粘贴下列内容:

FROM ubuntu
MAINTAINER Kimbro Staken version: 0.1
RUN apt-get update && apt-get install -y apache2 && apt-get clean && rm -rf /var/lib/apt/lists/*

ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2

EXPOSE 80

CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]

然后,构建镜像:

docker build -t apache .

(注意命令尾部的空格和圆点)

这将花费一些时间,然后你将看到如下的构建成功的消息:

Successfully built e7083fd898c7
Successfully tagged ng:latest
Swapnil:apache swapnil$

现在,我们来运行一下这个服务器:

$ docker run -d apache
a189a4db0f7c245dd6c934ef7164f3ddde09e1f3018b5b90350df8be85c8dc98

发现了吗,你的容器镜像已经运行了。可以运行如下的命令来检查所有运行的容器:

$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
a189a4db0f7 apache "/usr/sbin/apache2ctl" 10 seconds ago

你可以使用 docker kill 命令来杀死容器:

$docker kill a189a4db0f7

正如你所见,这个 “镜像” 它已经永久存在于你的目录中了,而不论运行与否。现在你可以根据你的需要创建很多的镜像,并且可以从这些镜像中繁衍出来更多的镜像。

这就是如何去创建镜像和运行容器。

想学习更多内容,你可以打开你的浏览器,然后找到更多的关于如何构建像 LAMP 栈这样的完整的 Docker 镜像的文档。这里有一个帮你实现它的 Dockerfile 文件。在下一篇文章中,我将演示如何推送一个镜像到 DockerHub。

你可以通过来自 Linux 基金会和 edX 的 “介绍 Linux” 免费课程来学习更多的知识。


via: https://www.linux.com/blog/learn/intro-to-linux/2018/1/how-create-docker-image

作者:SWAPNIL BHARTIYA 译者:qhwdw 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

所有人都知道 SSH 是一种远程登录工具,然而它也有许多其他用途。

创建一个 SOCKS 代理来浏览网页(也就是翻墙啦):

ssh -D <port> <remote_host>

设置 localhost:<port> 作为你浏览器的代理

连接一个堡垒机后的 Windows RDP 主机:

ssh -L <port>:<target_host>:3389 <bastion_server> 

让你的 RDP 客户端连接到 localhost:<port>

在不使用 VNC 端口的情况下,连接远程 VNC 主机:

ssh -L 5901:localhost:5901 <remote_host> 

让你的 VNC 客户端连接到 localhost:5901

按照这个思路,你可以映射任意端口:LDAP (389)、631 (CUPS)、8080 (替代的 HTTP),等等。

产生一个新的 SSH 密钥对:

ssh-keygen

更新密钥对的密码:

ssh-keygen -p

把公钥复制到远程主机上:

ssh-copy-id -i <identity file> <remote_host>

SSH 有一堆命令行选项,但是如果有一些是你经常使用的,你可以为它们在 SSH 配置文件 (${HOME}/.ssh/config) 里创建一个入口。比如:

host myhouse 
    User itsme 
    HostName house.example.com

那么你就可以输入 ssh myhouse 来代替 ssh [email protected]

以下是常用的命令行选项和他们的配置文件写法。一些是常用的简化写法。请查看 ssh(1)ssh_config(5) 的手册页来获取详尽信息。

命令行配置文件描述
-l <login name>User <login name>远程主机的登录用户名。
-i <identity file>IdentityFile <identity file>指定要使用的鉴权文件(SSH 密码对)。
-p <remote port>Port <remote port>远程 SSH 守护进程监听的端口号。 (默认为 22)
-CCompression <yes,no>压缩往来信息。 (默认为 no)
-D <port>DynamicForward <port>把本地端口的报文转发到远程主机。
-XForwardX11 <yes,no>把 X11 的图像数据转发到远程主机的端口. (默认为 no)
-AForwardAgent <yes,no>把授权代理的报文转发给远程主机。如果你使用第三方主机登录,这个功能将很有用。 (默认为 no)
-4(仅使用 IPv4) -6 (仅使用 IPv6)AddressFamily <any,inet4,inet6>指定仅使用 IPv4 或者 IPv6。
-L <local port>:<target host>:<target port>LocalForward <local port>:<target host>:<target port>把本地主机指定端口的报文转发到远程主机的某个端口。

opensource.com Twitter @opensourceway | facebook.com/opensourceway | IRC: #opensource.com on Freenode


作者简介:

Ben Cotton 是业余的气象学家和职业的高性能计算工程师。Ben 是微软 Azure 的产品营销经理,专注于高性能计算。他是一个 Fedora 用户和贡献者,共同创立了一个当地的开放源码群,并且是开源促进会的成员和保护自由软件的支持者。通过以下方式联系他 Twitter (@FunnelFiasco) 或者 FunnelFiasco.com.


via: https://opensource.com/sites/default/files/gated-content/cheat_sheet_ssh_v03.pdf

作者:BEN COTTON 译者:kennethXia 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

我已经主要使用 Linux 大约 10 年了,而且主要是 Ubuntu。但在最新发布的版本中,我决定重新回到我通常不喜欢的操作系统: Windows 10。

Ubuntu On Windows

我一直是 Linux 的粉丝,我最喜欢的两个发行版是 Debian 和 Ubuntu。现今作为一个服务器操作系统,Linux 是完美无暇的,但在桌面上一直存在不同程度的问题。

最近一系列的问题让我意识到,我不需要使用 Linux 作为我的桌面操作系统,我仍然是一个 Linux 粉丝,但基于我安装 Ubuntu 17.10 的经验,我已经决定回到 Windows。

什么使我选择了回归

问题是,当 Ubuntu 17.10 出来后,我像往常一样进行全新安装,但遇到了一些非常奇怪的新问题。

  • Dell D3100 Dock 不再工作(包括临时规避方案也没用)
  • Ubuntu 意外死机(随机)
  • 双击桌面上的图标没反应
  • 使用 HUD 搜索诸如“tweaks”之类的程序会尝试安装 META 桌面版本
  • GUI 比标准的 GNOME 感觉更糟糕

现在我确实考虑回到使用 Ubuntu 16.04 或另一个发行版,但是我觉得 Unity 7 是最精致的桌面环境,而另外唯一一个优雅且稳定的是 Windows 10。

除此之外,使用 Linux 而不是使用 Windows 也有一些固有的问题,如:

  • 大多数商用软件不可用,E.G Maya、 PhotoShop、 Microsoft Office(大多数情况下,替代品并不相同)等等。
  • 大多数游戏都没有移植到 Linux 上,包括来自 EA、 Rockstar Ect. 等主要工作室的游戏。
  • 对于大多数硬件来说,其 Linux 驱动程序是厂商的次要考虑。

在决定使用 Windows 之前,我确实考虑过其他发行版和操作系统。

与此同时,我看到了更多的“微软爱 Linux ”的行动,并且了解了 WSL。他们的新开发者的关注角度对我来说很有意思,于是我试了一下。

我在 Windows 找到了什么

我使用计算机主要是为了编程,我也使用虚拟机、git 和 ssh,并且大部分工作依赖于 bash。我偶尔也会玩游戏,观看 netflix 和一些轻松的办公室工作。

总之,我期待在 Ubuntu 中保留当前的工作流程并将其移植到 Windows 上。我也想利用 Windows 的优点。

  • 所有的 PC 游戏支持 Windows
  • 大多数程序是原生的
  • 微软办公软件

虽然使用 Windows 有很多坑,但是我打算正确对待它,所以我不担心一般的 Windows 故障,例如病毒和恶意软件。

Windows 的子系统 Linux(Windows 上的 Ubuntu 中的 Bash)

微软与 Canonical 的密切合作将 Ubuntu 带到了 Windows 上。在经过快速设置和启动程序之后,你将拥有非常熟悉的 bash 界面。

我一直在研究其局限性,但是在写这篇文章时我碰到的唯一真正的限制是它从硬件中抽象了出来。例如,lsblk 不会显示你有什么分区,因为子系统里的 Ubuntu 没有提供这些信息。

但是除了访问底层工具之外,我发现其体验非常熟悉,也很棒。

我在下面的工作流程中使用了它。

  • 生成 SSH 密钥对
  • 使用 Git 和 Github 来管理我的仓库
  • SSH 到几个服务器,包括不用密码
  • 为本地数据库运行 MySQL
  • 监视系统资源
  • 使用 Vim 编辑配置文件
  • 运行 Bash 脚本
  • 运行本地 Web 服务器
  • 运行 PHP、NodeJS

到目前为止,它已经被证明是非常强大的工具。除了是在 Windows 10 用户界面之中,我的工作流程感觉和我在 Ubuntu 上几乎一样。尽管我的多数工作可以在 WSL 中处理,但我仍然打算通过虚拟机进行更深入的工作,这可能超出了 WSL 的范围。

不需要用 Wine

我遇到的另一个主要问题是兼容性问题。我很少使用 Wine 来使用 Windows 软件。(LCTT 译注:Wine 是可以使 Linux 上运行 Windows 应用的软件)但是有时它是必需的,尽管通常体验不是很好。

HeidiSQL

我首先安装的程序之一是 HeidiSQL,它是我最喜欢的数据库客户端之一。它可以在 Wine 下工作,但是感觉很不好,所以我在 Linux 下丢掉它而使用了 MySQL Workbench。回到了 Windows 中,就像一个可靠的老朋友回来了。

游戏平台 / Steam

没有游戏的 Windows 电脑是无法想象的。我从 Steam 的网站上安装了它,我的 Linux 游戏,加上我的 Windows 游戏就变大了 5 倍,并且包括 GTA V (LCTT 译注: GTA V 是一款名叫侠盗飞车的游戏) 等 AAA 级游戏。而这些我在 Ubuntu 中只能梦想。

我对 SteamOS 有很大的期望,并且一直会持续如此。但是我认为在可预见的将来,它不会在任何地方的游戏市场中崭露头角。所以如果你想在 PC 上玩游戏,你确实需要 Windows。

还有一点需要注意的是, 你的 nvidia 显卡的驱动程序会得到很好的支持,这使得像 TF2 (LCTT 译注: 这是一款名叫军团要塞 2 的游戏)这样的一些 Linux 原生游戏运行的稍好一些。

Windows 在游戏方面总是优越的,所以这并不令人感到意外。

从 USB 硬盘运行,为什么

我在我的主固态硬盘上运行 Linux,但在过去,我是从 usb 棒和 usb 硬盘运行它的。我习惯了 Linux 的这种持久性,这让我可以在不丢失主要操作系统的情况下长期尝试多个版本。现在我尝试将 Windows 安装到 USB 连接的硬盘上时,它无法工作也不可能工作。所以当我将 Windows 硬盘分区的克隆作为备份时,我很惊讶我可以通过 USB 启动它。

这对我来说已经成为一个方便的选择,因为我打算将我的工作笔记本电脑迁移回 Windows,但如果不想冒险,那就把它扔在那里吧。

所以我在过去的几天里,我使用 USB 来运行它,除了一些错误的消息外,我没有通过 USB 运行发现它真正的缺点。

这样做主要的问题是:

  • 较慢的启动速度
  • 恼人的信息:不要拔掉你的 USB
  • 无法激活它

我可能会写一篇关于 USB 驱动器上的 Windows 的文章,这样我们可以有更详细的了解。

那么结论是什么?

我使用 Windows 10 大约两周了,并没有注意到它对我的工作流程有任何的负面影响。尽管过程会有一些小问题,但我需要的所以工具都在手边,并且操作系统一般都在运行。

我会留在 Windows吗?

虽然现在还为时尚早,但我想在可见的未来我会坚持使用 Windows。


via: https://www.chris-shaw.com/blog/my-adventure-migrating-back-to-windows

作者:Christopher Shaw 译者:MjSeven 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Linux 中的打印

虽然现在大量的沟通都是电子化和无纸化的,但是在我们的公司中还有大量的材料需要打印。银行结算单、公用事业帐单、财务和其它报告、以及收益结算单等一些东西还是需要打印的。本教程将介绍在 Linux 中如何使用 CUPS 去打印。

CUPS,是 通用 Unix 打印系统 Common UNIX Printing System 的首字母缩写,它是 Linux 中的打印机和打印任务的管理者。早期计算机上的打印机一般是在特定的字符集和字体大小下打印文本文件行。现在的图形打印机可以打印各种字体和大小的文本和图形。尽管如此,现在你所使用的一些命令,在古老的行式打印守护进程(LPD)技术的历史中仍能找到它们。

本教程将帮你了解 Linux 服务器专业考试(LPIC-1)的第 108 号主题的 108.4 目标。这个目标的权重为 2。

前提条件

为了更好地学习本系列教程,你需要具备基本的 Linux 知识,和使用 Linux 系统实践本教程中的命令的能力,你应该熟悉 GNU 和 UNIX® 命令的使用。有时不同版本的程序输出可能会不同,因此,你的结果可能与本教程中的示例有所不同。

本教程中的示例使用的是 Fedora 27 的系统。

有关打印的一些历史

这一小部分历史并不是 LPI 目标的,但它有助于你理解这个目标的相关环境。

早期的计算机大都使用行式打印机。这些都是击打式打印机,那时,它们使用固定间距的字符和单一的字体来打印文本行。为提升整个系统性能,早期的主机要与慢速的外围设备(如读卡器、卡片穿孔机、和运行其它工作的行式打印机)交叉进行工作。因此就产生了在线的或者假脱机的同步外围操作,这一术语目前在谈到计算机打印时仍然在使用。

在 UNIX 和 Linux 系统上,打印初始化使用的是 BSD( 伯克利软件分发版 Berkeley Software Distribution )打印子系统,它是由一个作为服务器运行的行式打印守护程序(LPD)组成,而客户端命令如 lpr 是用于提交打印作业。这个协议后来被 IETF 标准化为 RFC 1179 —— 行式打印机守护进程协议

System V 也有一个打印守护程序。它的功能与BSD 的 LPD 守护程序类似,但是它们的命令集不一样。你在后面会经常看到完成相同的任务使用不同选项的两个命令。例如,对于打印文件的命令,伯克利实现版本是 lpr,而 System V 实现版本是 lp

随着打印机技术的进步,在一个页面上混合出现不同字体成为可能,并且可以将图片像文字一样打印。可变间距字体,以及更多先进的打印技术,比如间距和连字符,现在都已经标准化。出现了几种对基本的 lpd/lpr 方法等改进设计,比如 LPRng,下一代的 LPR,以及 CUPS。

许多可以打印图形的打印机,使用 Adobe PostScript 语言进行初始化。一个 PostScript 打印机有一个解释器引擎,它可以解释打印任务中的命令并从这些命令中生成最终的页面。PostScript 经常被用做原始文件(比如一个文本文件或者一个图像文件)和最终格式没有适合的 PostScript 功能的特定打印机之间的中间层。转换这些特定的打印任务,比如将一个 ASCII 文本文件或者一个 JPEG 图像转换为 PostScript,然后再使用过滤器转换 PostScript 到非 PostScript 打印机所需要的最终光栅格式。

现在的 便携式文档格式 Portable Document Format (PDF),它就是基于 PostScript 的,已经替换了传统的原始 PostScript。PDF 设计为与硬件和软件无关,它封装了要打印的页面的完整描述。你可以查看 以及打印 PDF 文件。

管理打印队列

用户直接打印作业到一个名为 打印队列 print queue 的逻辑实体。在单用户系统中,打印队列和打印机通常是几乎相同的意思。但是,CUPS 允许系统不用连接到一个打印机上,而最终在一个远程系统上的排队打印作业,并且通过使用分类,允许将定向到一个分类的打印作业在该分类第一个可用的打印机上打印。

你可以检查和管理打印队列。对于 CUPS 来说,其中一些命令实现了一些新操作。另外的一些是源于 LPD 的兼容命令,不过现在的一些选项通常是最初的 LPD 打印系统选项的有限子集。

你可以使用 CUPS 的 lpstat 命令去检查队列,以了解打印系统。一些常见选项如下表 1。

选项作用
-a显示打印机状态
-c显示打印分类
-p显示打印状态:enabled 或者 disabled
-s显示默认打印机、打印机和类。相当于 -d -c -v注意:要指定多个选项,这些选项必须像值一样分隔开。
-v显示打印机和它们的设备。

表 1. lpstat 命令的选项

你也可以使用 LPD 的 lpc 命令(它可以在 /usr/sbin 中找到)使用它的 status 选项。如果你不想指定打印机名字,将列出所有的队列。列表 1 展示了命令的一些示例。

[ian@atticf27 ~]$ lpstat -d
system default destination: HL-2280DW
[ian@atticf27 ~]$ lpstat -v HL-2280DW
device for HL-2280DW: dnssd://Brother%20HL-2280DW._pdl-datastream._tcp.local/
[ian@atticf27 ~]$ lpstat -s
system default destination: HL-2280DW
members of class anyprint:
    HL-2280DW
    XP-610
device for anyprint: ///dev/null
device for HL-2280DW: dnssd://Brother%20HL-2280DW._pdl-datastream._tcp.local/
device for XP-610: dnssd://EPSON%20XP-610%20Series._ipp._tcp.local/?uuid=cfe92100-67c4-11d4-a45f-ac18266c48aa
[ian@atticf27 ~]$ lpstat -a XP-610
XP-610 accepting requests since Thu 27 Apr 2017 05:53:59 PM EDT
[ian@atticf27 ~]$ /usr/sbin/lpc status HL-2280DW
HL-2280DW:
    printer is on device 'dnssd' speed -1
    queuing is disabled
    printing is enabled
    no entries
    daemon present

列表 1. 显示可用打印队列

这个示例展示了两台打印机 —— HL-2280DW 和 XP-610,和一个分类 anyprint,它允许打印作业定向到这两台打印机中的第一个可用打印机。

在这个示例中,已经禁用了打印到 HL-2280DW 队列,但是打印功能是启用的,这样便于将打印机脱机维护之前可以完成打印队列中的任务。启用还是禁用队列,可以使用 cupsacceptcupsreject 命令来管理。以前它们叫做 acceptreject,你或许可能在 /usr/sbin 中找到这些命令,但它们现在都是符号链接到新的命令上了。同样,启用还是禁用打印,你可以使用 cupsenablecupsdisable 命令来管理。在早期版本的 CUPS 中,这些被称为 enabledisable,它也许会与 bash shell 内置的 enable 混淆。列表 2 展示了如何去启用打印机 HL-2280DW 上的队列,而禁止它的打印。CUPS 的几个命令支持使用 -r 选项去提供一个该操作的理由。这个理由会在你使用 lpstat 时显示,但是如果你使用的是 lpc 命令则不会显示它。

[ian@atticf27 ~]$ lpstat -a -p HL-2280DW
anyprint accepting requests since Mon 29 Jan 2018 01:17:09 PM EST
HL-2280DW not accepting requests since Thu 27 Apr 2017 05:52:27 PM EDT -
    Maintenance scheduled
XP-610 accepting requests since Thu 27 Apr 2017 05:53:59 PM EDT
printer HL-2280DW is idle. enabled since Thu 27 Apr 2017 05:52:27 PM EDT
    Maintenance scheduled
[ian@atticf27 ~]$ accept HL-2280DW
[ian@atticf27 ~]$ cupsdisable -r "waiting for toner delivery" HL-2280DW
[ian@atticf27 ~]$ lpstat -p -a
printer anyprint is idle. enabled since Mon 29 Jan 2018 01:17:09 PM EST
printer HL-2280DW disabled since Mon 29 Jan 2018 04:03:50 PM EST -
    waiting for toner delivery
printer XP-610 is idle. enabled since Thu 27 Apr 2017 05:53:59 PM EDT
anyprint accepting requests since Mon 29 Jan 2018 01:17:09 PM EST
HL-2280DW accepting requests since Mon 29 Jan 2018 04:03:50 PM EST
XP-610 accepting requests since Thu 27 Apr 2017 05:53:59 PM EDT

列表 2. 启用队列和禁用打印

注意:用户执行这些任务必须经过授权。它可能要求是 root 用户或者其它的授权用户。在 /etc/cups/cups-files.conf 中可以看到 SystemGroup 的条目,cups-files.conf 的 man 页面有更多授权用户组的信息。

管理用户打印作业

现在,你已经知道了一些如何去检查打印队列和类的方法,我将给你展示如何管理打印队列上的作业。你要做的第一件事是,如何找到一个特定打印机或者全部打印机上排队的任意作业。完成上述工作要使用 lpq 命令。如果没有指定任何选项,lpq 将显示默认打印机上的队列。使用 -P 选项和一个打印机名字将指定打印机,或者使用 -a 选项去指定所有的打印机,如下面的列表 3 所示。

[pat@atticf27 ~]$ # As user pat (non-administrator)
[pat@atticf27 ~]$ lpq
HL-2280DW is not ready
Rank Owner Job File(s) Total Size
1st unknown 4 unknown 6144 bytes
2nd pat 6 bitlib.h 6144 bytes
3rd pat 7 bitlib.C 6144 bytes
4th unknown 8 unknown 1024 bytes
5th unknown 9 unknown 1024 bytes

[ian@atticf27 ~]$ # As user ian (administrator)
[ian@atticf27 ~]$ lpq -P xp-610
xp-610 is ready
no entries
[ian@atticf27 ~]$ lpq -a
Rank Owner Job File(s) Total Size
1st ian 4 permutation.C 6144 bytes
2nd pat 6 bitlib.h 6144 bytes
3rd pat 7 bitlib.C 6144 bytes
4th ian 8 .bashrc 1024 bytes
5th ian 9 .bashrc 1024 bytes

列表 3. 使用 lpq 检查打印队列

在这个示例中,共有五个作业,它们是 4、6、7、8、和 9,并且它是名为 HL-2280DW 的打印机的队列,而不是 XP-610 的。在这个示例中使用 -P 选项,可简单地显示哪个打印机已经准备好,但是没有队列任务。注意,CUPS 的打印机命名,是大小写不敏感的。还要注意的是,用户 ian 提交了同样的作业两次,当一个作业没有第一时间打印时,经常能看到用户的这种动作。

一般情况下,你可能会查看或者维护你自己的打印作业,但是,root 用户或者其它授权的用户通常会去管理其它打印作业。大多数 CUPS 命令都可以使用一个 -E 选项,对 CUPS 服务器与客户端之间的通讯进行加密。

使用 lprm 命令从队列中去删除一个 .bashrc 作业。如果不使用选项,将删除当前的作业。使用 - 选项,将删除全部的作业。要么就如列表 4 那样,指定一个要删除的作业列表。

[[pat@atticf27 ~]$ # As user pat (non-administrator)
[pat@atticf27 ~]$ lprm
lprm: Forbidden

[ian@atticf27 ~]$ # As user ian (administrator)
[ian@atticf27 ~]$ lprm 8
[ian@atticf27 ~]$ lpq
HL-2280DW is not ready
Rank Owner Job File(s) Total Size
1st ian 4 permutation.C 6144 bytes
2nd pat 6 bitlib.h 6144 bytes
3rd pat 7 bitlib.C 6144 bytes
4th ian 9 .bashrc 1024 bytes

列表 4. 使用 lprm 删除打印作业

注意,用户 pat 不能删除队列中的第一个作业,因为它是用户 ian 的。但是,ian 可以删除他自己的 8 号作业。

另外的可以帮你操作打印队列中的作业的命令是 lp。使用它可以去修改作业属性,比如打印数量或者优先级。我们假设用户 ian 希望他的作业 9 在用户 pat 的作业之前打印,并且希望打印两份。作业优先级的默认值是 50,它的优先级范围从最低的 1 到最高的 100 之间。用户 ian 可以使用 -i-n、以及 -q 选项去指定一个要修改的作业,而新的打印数量和优先级可以如下面的列表 5 所示的那样去修改。注意,使用 -l 选项的 lpq 命令可以提供更详细的输出。

[ian@atticf27 ~]$ lpq
HL-2280DW is not ready
Rank Owner Job File(s) Total Size
1st ian 4 permutation.C 6144 bytes
2nd pat 6 bitlib.h 6144 bytes
3rd pat 7 bitlib.C 6144 bytes
4th ian 9 .bashrc 1024 bytes
[ian@atticf27 ~]$ lp -i 9 -q 60 -n 2
[ian@atticf27 ~]$ lpq
HL-2280DW is not ready
Rank Owner Job File(s) Total Size
1st ian 9 .bashrc 1024 bytes
2nd ian 4 permutation.C 6144 bytes
3rd pat 6 bitlib.h 6144 bytes
4th pat 7 bitlib.C 6144 bytes

列表 5. 使用 lp 去改变打印数量和优先级

最后,lpmove 命令可以允许一个作业从一个队列移动到另一个队列。例如,我们可能因为打印机 HL-2280DW 现在不能使用,而想去移动一个作业到另外的队列上。你可以指定一个作业编号,比如 9,或者你可以用一个队列名加一个连字符去限定它,比如,HL-2280DW-0。lpmove 命令的操作要求是授权用户。列表 6 展示了如何去从一个队列移动作业到另外的队列,先是指定打印机和作业 ID 移动,然后是移动指定打印机的所有作业。稍后我们可以去再次检查队列,其中一个作业已经在打印中了。

[ian@atticf27 ~]$ lpmove HL-2280DW-9 anyprint
[ian@atticf27 ~]$ lpmove HL-2280DW xp-610
[ian@atticf27 ~]$ lpq -a
Rank Owner Job File(s) Total Size
active ian 9 .bashrc 1024 bytes
1st ian 4 permutation.C 6144 bytes
2nd pat 6 bitlib.h 6144 bytes
3rd pat 7 bitlib.C 6144 bytes
[ian@atticf27 ~]$ # A few minutes later
[ian@atticf27 ~]$ lpq -a
Rank Owner Job File(s) Total Size
active pat 6 bitlib.h 6144 bytes
1st pat 7 bitlib.C 6144 bytes

列表 6. 使用 lpmove 移动作业到另外一个打印队列

如果你使用的是 CUPS 之外的打印服务器,比如 LPD 或者 LPRng,大多数的队列管理功能是由 lpc 命令的子命令来处理的。例如,你可以使用 lpc topq 去移动一个作业到队列的顶端。其它的 lpc 子命令包括 disabledownenableholdmoveredirectrelease、和 start。这些子命令在 CUPS 的兼容命令中没有实现。

打印文件

如何去打印创建的作业?大多数图形界面程序都提供了一个打印方法,通常是 文件 菜单下面的选项。这些程序为选择打印机、设置页边距、彩色或者黑白打印、打印数量、选择每张纸打印的页面数(每张纸打印两个页面,通常用于讲义)等等,都提供了图形化的工具。现在,我将为你展示如何使用命令行工具去管理这些功能,然后和图形化实现进行比较。

打印文件最简单的方法是使用 lpr 命令,然后提供一个文件名字。这将在默认打印机上打印这个文件。而 lp 命令不仅可以打印文件,也可以修改打印作业。列表 7 展示了使用这个命令的一个简单示例。注意,lpr 会静默处理这个作业,但是 lp 会显示处理后的作业的 ID。

[ian@atticf27 ~]$ echo "Print this text" > printexample.txt
[ian@atticf27 ~]$ lpr printexample.txt
[ian@atticf27 ~]$ lp printexample.txt
request id is HL-2280DW-12 (1 file(s))

列表 7. 使用 lpr 和 lp 打印

表 2 展示了 lpr 上你可以使用的一些选项。注意, lp 的选项和 lpr 的很类似,但是名字可能不一样;例如,-#lpr 上是相当于 lp-n 选项。查看 man 页面了解更多的信息。

选项作用
-C-J-T设置一个作业名字。
-P选择一个指定的打印机。
-#指定打印数量。注意这不同于 lp 命令的 -n 选项。
-m在作业完成时发送电子邮件。
-l表示打印文件已经为打印做好格式准备。相当于 -o raw
-o设置一个作业选项。
-p格式化一个带有阴影标题的文本文件。相关于 -o prettyprint
-q暂缓(或排队)后面的打印作业。
-r在文件进入打印池之后,删除文件。

表 2. lpr 的选项

列表 8 展示了一些选项。我要求打印之后给我发确认电子邮件,那个作业被暂缓执行,并且在打印之后删除文件。

[ian@atticf27 ~]$ lpr -P HL-2280DW -J "Ian's text file" -#2 -m -p -q -r printexample.txt
[[ian@atticf27 ~]$ lpq -l
HL-2280DW is ready


ian: 1st [job 13 localhost]
 2 copies of Ian's text file 1024 bytes
[ian@atticf27 ~]$ ls printexample.txt
ls: cannot access 'printexample.txt': No such file or directory

列表 8. 使用 lpr 打印

我现在有一个在 HL-2280DW 打印队列上暂缓执行的作业。然后怎么做?lp 命令可以通过使用 -H 的各种选项来暂缓或者投放作业。列表 9 展示了如何投放被暂缓的作业。查看 lp 命令的 man 页面了解其它选项的信息。

[ian@atticf27 ~]$ lp -i 13 -H resume

列表 9. 重启一个暂缓的打印作业

并不是所有的可用打印机都支持相同的选项集。使用 lpoptions 命令去查看一个打印机的常用选项。添加 -l 选项去显示打印机专用的选项。列表 10 展示了两个示例。许多常见的选项涉及到人像/风景打印、页面大小和输出在纸张上的布局。详细信息查看 man 页面。

[ian@atticf27 ~]$ lpoptions -p HL-2280DW
copies=1 device-uri=dnssd://Brother%20HL-2280DW._pdl-datastream._tcp.local/
finishings=3 job-cancel-after=10800 job-hold-until=no-hold job-priority=50
job-sheets=none,none marker-change-time=1517325288 marker-colors=#000000,#000000
marker-levels=-1,92 marker-names='Black\ Toner\ Cartridge,Drum\ Unit'
marker-types=toner,opc number-up=1 printer-commands=none
printer-info='Brother HL-2280DW' printer-is-accepting-jobs=true
printer-is-shared=true printer-is-temporary=false printer-location
printer-make-and-model='Brother HL-2250DN - CUPS+Gutenprint v5.2.13 Simplified'
printer-state=3 printer-state-change-time=1517325288 printer-state-reasons=none
printer-type=135188 printer-uri-supported=ipp://localhost/printers/HL-2280DW
sides=one-sided

[ian@atticf27 ~]$ lpoptions -l -p xp-610
PageSize/Media Size: *Letter Legal Executive Statement A4
ColorModel/Color Model: *Gray Black
InputSlot/Media Source: *Standard ManualAdj Manual MultiPurposeAdj MultiPurpose
UpperAdj Upper LowerAdj Lower LargeCapacityAdj LargeCapacity
StpQuality/Print Quality: None Draft *Standard High
Resolution/Resolution: *301x300dpi 150dpi 300dpi 600dpi
Duplex/2-Sided Printing: *None DuplexNoTumble DuplexTumble
StpiShrinkOutput/Shrink Page If Necessary to Fit Borders: *Shrink Crop Expand
StpColorCorrection/Color Correction: *None Accurate Bright Hue Uncorrected
Desaturated Threshold Density Raw Predithered
StpBrightness/Brightness: 0 100 200 300 400 500 600 700 800 900 *None 1100
1200 1300 1400 1500 1600 1700 1800 1900 2000 Custom.REAL
StpContrast/Contrast: 0 100 200 300 400 500 600 700 800 900 *None 1100 1200
1300 1400 1500 1600 1700 1800 1900 2000 2100 2200 2300 2400 2500 2600 2700
2800 2900 3000 3100 3200 3300 3400 3500 3600 3700 3800 3900 4000 Custom.REAL
StpImageType/Image Type: None Text Graphics *TextGraphics Photo LineArt

列表 10. 检查打印机选项

大多数的 GUI 应用程序有一个打印对话框,通常你可以使用 文件 >打印 菜单去选择它。图 1 展示了在 GIMP 中的一个示例,GIMP 是一个图像处理程序。

Printing from the GIMP

图 1. 在 GIMP 中打印

到目前为止,我们所有的命令都是隐式指向到本地的 CUPS 打印服务器上。你也可以通过指定 -h 选项和一个端口号(如果不是 CUPS 的默认端口号 631 的话)将打印转向到另外一个系统上的服务器。

CUPS 和 CUPS 服务器

CUPS 打印系统的核心是 cupsd 打印服务器,它是一个运行的守护进程。CUPS 配置文件一般位于 /etc/cups/cupsd.conf/etc/cups 目录也有与 CUPS 相关的其它的配置文件。CUPS 一般在系统初始化期间启动,根据你的发行版不同,它也可能通过位于 /etc/rc.d/init.d 或者 /etc/init.d 目录中的 CUPS 脚本来控制。对于 最新使用 systemd 来初始化的系统,CUPS 服务脚本可能在 /usr/lib/systemd/system/cups.service 中。和大多数使用脚本的服务一样,你可以停止、启动、或者重启守护程序。查看我们的教程:学习 Linux,101:运行级别、引导目标、关闭、和重启动,了解使用初始化脚本的更多信息。

配置文件 /etc/cups/cupsd.conf 包含一些管理参数,比如访问打印系统、是否允许远程打印、本地打印池文件等等。在一些系统上,第二部分单独描述了打印队列,它一般是由配置工具自动生成的。列表 11 展示了一个默认的 cupsd.conf 文件中的一些条目。注意,注释是以 # 字符开头的。默认值通常以注释的方式显示,并且可以通过删除前面的 # 字符去改变默认值。

# Only listen for connections from the local machine.
Listen localhost:631
Listen /var/run/cups/cups.sock

# Show shared printers on the local network.
Browsing On
BrowseLocalProtocols dnssd

# Default authentication type, when authentication is required...
DefaultAuthType Basic

# Web interface setting...
WebInterface Yes

# Set the default printer/job policies...
<Policy default>
 # Job/subscription privacy...
 JobPrivateAccess default
 JobPrivateValues default
 SubscriptionPrivateAccess default
 SubscriptionPrivateValues default

 # Job-related operations must be done by the owner or an administrator...
 <Limit Create-Job Print-Job Print-URI Validate-Job>
 Order deny,allow
 </Limit>

列表 11. 默认的 /etc/cups/cupsd.conf 文件的部分内容

可以用在 cupsd.conf 中使用的文件、目录、和用户配置命令,现在都存储在作为替代的 cups-files.conf 中。这是为了防范某些类型的提权攻击。列表 12 展示了 cups-files.conf 文件中的一些条目。注意,正如在文件层次结构标准(FHS)中所期望的那样,打印池文件默认保存在文件系统的 /var/spool 目录中。查看 man 页面了解 cupsd.confcups-files.conf 配置文件的更多信息。

# Location of the file listing all of the local printers...
#Printcap /etc/printcap

# Format of the Printcap file...
#PrintcapFormat bsd
#PrintcapFormat plist
#PrintcapFormat solaris

# Location of all spool files...
#RequestRoot /var/spool/cups

# Location of helper programs...
#ServerBin /usr/lib/cups

# SSL/TLS keychain for the scheduler...
#ServerKeychain ssl

# Location of other configuration files...
#ServerRoot /etc/cups

列表 12. 默认的 /etc/cups/cups-files.conf 配置文件的部分内容

列表 12 提及了 /etc/printcap 文件。这是 LPD 打印服务器的配置文件的名字,并且一些应用程序仍然使用它去确定可用的打印机和它们的属性。它通常是在 CUPS 系统上自动生成的,因此,你可能没有必要去修改它。但是,如果你在诊断用户打印问题,你可能需要去检查它。列表 13 展示了一个示例。

# This file was automatically generated by cupsd(8) from the
# /etc/cups/printers.conf file. All changes to this file
# will be lost.
HL-2280DW|Brother HL-2280DW:rm=atticf27:rp=HL-2280DW:
anyprint|Any available printer:rm=atticf27:rp=anyprint:
XP-610|EPSON XP-610 Series:rm=atticf27:rp=XP-610:

列表 13. 自动生成的 /etc/printcap

这个文件中的每一行都有一个打印机名字、打印机描述,远程机器(rm)的名字、以及那个远程机器上的远程打印机(rp)。老的 /etc/printcap 文件也描述了打印机的能力。

文件转换过滤器

你可以使用 CUPS 打印许多类型的文件,包括明文的文本文件、PDF、PostScript、和各种格式的图像文件,你只需要提供要打印的文件名,除此之外你再无需向 lprlp 命令提供更多的信息。这个神奇的壮举是通过使用过滤器来实现的。实际上,这些年来最流行的过滤器就就叫做 magicfilter(神奇的过滤器)。

当打印一个文件时,CUPS 使用多用途因特网邮件扩展(MIME)类型去决定合适的转换过滤器。其它的打印数据包可能使用由 file 命令使用的神奇数字机制。关于 file 或者神奇数的更多信息可以查看它们的 man 页面。

输入文件被过滤器转换成中间层的光栅格式或者 PostScript 格式。一些作业信息,比如打印数量也会被添加进去。数据最终通过一个后端发送到目标打印机。还有一些可以用手动过滤的输入文件的过滤器(如 a2ps 或 dvips)。你可以通过这些过滤器获得特殊格式的结果,或者去处理一些 CUPS 原生并不支持的文件格式。

添加打印机

CUPS 支持多种打印机,包括:

  • 本地连接的并行口和 USB 口打印机
  • 因特网打印协议(IPP)打印机
  • 远程 LPD 打印机
  • 使用 SAMBA 的 Microsoft® Windows® 打印机
  • 使用 NCP 的 Novell 打印机
  • HP Jetdirect 打印机

当系统启动或者设备连接时,现在的大多数系统都会尝试自动检测和自动配置本地硬件。同样,许多网络打印机也可以被自动检测到。使用 CUPS 的 web 管理工具(http://localhost:631或者http://127.0.0.1:631)去搜索或添加打印机。许多发行版都包含它们自己的配置工具,比如,在 SUSE 系统上的 YaST。图 2 展示了使用 localhost:631 的 CUPS 界面,图 3 展示了 Fedora 27 上的 GNOME 打印机设置对话框。

Using the CUPS web interface

图 2. 使用 CUPS 的 web 界面

Using printer settings on Fedora 27

图 3. Fedora 27 上的打印机设置

你也可以从命令行配置打印机。在配置打印机之前,你需要一些关于打印机和它的连接方式的基本信息。如果是一个远程系统,你还需要一个用户 ID 和密码。

你需要去知道你的打印机使用什么样的驱动程序。不是所有的打印机都支持 Linux,有些打印机在 Linux 上压根就不能使用,或者功能受限。你可以去 OpenPrinting.org 去查看是否有你的特定的打印机的驱动程序。lpinfo 命令也可以帮你识别有效的设备类型和驱动程序。使用 -v 选项去列出支持的设备,使用 -m 选项去列出驱动程序,如列表 14 所示。

[ian@atticf27 ~]$ lpinfo -m | grep -i xp-610
lsb/usr/Epson/epson-inkjet-printer-escpr/Epson-XP-610_Series-epson-escpr-en.ppd.gz
EPSON XP-610 Series, Epson Inkjet Printer Driver (ESC/P-R) for Linux
[ian@atticf27 ~]$ locate "Epson-XP-610_Series-epson-escpr-en.ppd.gz"
/usr/share/ppd/Epson/epson-inkjet-printer-escpr/Epson-XP-610_Series-epson-escpr-en.ppd.gz
[ian@atticf27 ~]$ lpinfo -v
network socket
network ipps
network lpd
network beh
network ipp
network http
network https
direct hp
serial serial:/dev/ttyS0?baud=115200
direct parallel:/dev/lp0
network smb
direct hpfax
network dnssd://Brother%20HL-2280DW._pdl-datastream._tcp.local/
network dnssd://EPSON%20XP-610%20Series._ipp._tcp.local/?uuid=cfe92100-67c4-11d4-a45f-ac18266c48aa
network lpd://BRN001BA98A1891/BINARY_P1
network lpd://192.168.1.38:515/PASSTHRU

列表 14. 可用的打印机驱动程序

这个 Epson-XP-610\_Series-epson-escpr-en.ppd.gz 驱动程序在我的系统上位于 /usr/share/ppd/Epson/epson-inkjet-printer-escpr/ 目录中。

如果你找不到驱动程序,你可以到打印机生产商的网站看看,说不定会有专用的驱动程序。例如,在写这篇文章的时候,Brother 就有一个我的 HL-2280DW 打印机的驱动程序,但是,这个驱动程序在 OpenPrinting.org 上还没有列出来。

如果你收集齐了基本信息,你可以如列表 15 所示的那样,使用 lpadmin 命令去配置打印机。为此,我将为我的 HL-2280DW 打印机创建另外一个实例,以便于双面打印。

[ian@atticf27 ~]$ lpinfo -m | grep -i "hl.*2280"
HL2280DW.ppd Brother HL2280DW for CUPS
lsb/usr/HL2280DW.ppd Brother HL2280DW for CUPS
[ian@atticf27 ~]$ lpadmin -p HL-2280DW-duplex -E -m HL2280DW.ppd \
> -v dnssd://Brother%20HL-2280DW._pdl-datastream._tcp.local/ \
> -D "Brother 1" -o sides=two-sided-long-edge
[ian@atticf27 ~]$ lpstat -a
anyprint accepting requests since Mon 29 Jan 2018 01:17:09 PM EST
HL-2280DW accepting requests since Tue 30 Jan 2018 10:56:10 AM EST
HL-2280DW-duplex accepting requests since Wed 31 Jan 2018 11:41:16 AM EST
HXP-610 accepting requests since Mon 29 Jan 2018 10:34:49 PM EST

列表 15. 配置一台打印机

你可以使用带 -c 选项的 lpadmin 命令去创建一个仅用于双面打印的新分类,而不用为了双面打印去创建一个打印机的副本。

如果你需要删除一台打印机,使用带 -x 选项的 lpadmin 命令。

列表 16 展示了如何去删除打印机和创建一个替代类。

[ian@atticf27 ~]$ lpadmin -x HL-2280DW-duplex
[ian@atticf27 ~]$ lpadmin -p HL-2280DW -c duplex -E -D "Duplex printing" -o sides=two-sided-long-edge
[ian@atticf27 ~]$ cupsenable duplex
[ian@atticf27 ~]$ cupsaccept duplex
[ian@atticf27 ~]$ lpstat -a
anyprint accepting requests since Mon 29 Jan 2018 01:17:09 PM EST
duplex accepting requests since Wed 31 Jan 2018 12:12:05 PM EST
HL-2280DW accepting requests since Wed 31 Jan 2018 11:51:16 AM EST
XP-610 accepting requests since Mon 29 Jan 2018 10:34:49 PM EST

列表 16. 删除一个打印机和创建一个类

你也可以使用 lpadmin 或者 lpoptions 命令去设置各种打印机选项。详细信息请查看 man 页面。

排错

如果你有打印问题,尝试下列的提示:

  • 确保 CUPS 服务器正在运行。你可以使用 lpstat 命令,如果它不能连接到 cupsd 守护程序,它将会报告一个错误。或者,你可以使用 ps -ef 命令在输出中去检查是否有 cupsd。
  • 如果你试着排队一个打印作业而得到一个错误信息,指示打印机不接受这个作业,你可以使用 lpstat -a 或者 lpc status 去检查那个打印机是否接受作业。
  • 如果一个队列中的作业没有打印,使用 lpstat -plpc status 去检查那个打印机是否接受作业。如前面所讨论的那样,你可能需要将这个作业移动到其它的打印机。
  • 如果这个打印机是远程的,检查它在远程系统上是否存在,并且是可操作的。
  • 检查配置文件,确保特定的用户或者远程系统允许在这个打印机上打印。
  • 确保防火墙允许远程打印请求,是否允许从其它系统到你的系统,或者从你的系统到其它系统的数据包通讯。
  • 验证是否有正确的驱动程序。

正如你所见,打印涉及到你的系统中的几个组件,甚至还有网络。在本教程中,基于篇幅的考虑,我们仅能给你的诊断提供了几个着手点。大多数的 CUPS 系统也有实现我们所讨论的命令行功能的图形界面。一般情况下,这个界面是从本地主机使用浏览器指向 631 端口(http://localhost:631或http://127.0.0.1:631)来访问的,如前面的图 2 所示。

你可以通过将 CUPS 运行在前台而不是做为一个守护进程来诊断它的问题。如果有需要,你也可以通过这种方式去测试替代的配置文件。运行 cupsd -h 获得更多信息,或者查看 man 页面。

CUPS 也带有一个访问日志和错误日志。你可以在 cupsd.conf 中使用 LogLevel 语句来改变日志级别。默认情况下,日志是保存在 /var/log/cups 目录。它们可以在浏览器界面(http://localhost:631)下,从 Administration 选项卡中查看。使用不带任何选项的 cupsctl 命令可以显示日志选项。也可以编辑 cupsd.conf 或者使用 cupsctl 去调整各种日志参数。查看 cupsctl 命令的 man 页面了解更多信息。

在 Ubuntu 的 Wiki 页面上的 调试打印问题 页面也是一个非常好的学习的地方。

这就是关于打印和 CUPS 的介绍。


via: https://www.ibm.com/developerworks/library/l-lpic1-108-4/index.html

作者:Ian Shields 译者:qhwdw 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

使用 SQL 构建一个关系数据库比你想的更容易。

使用 SQL 构建数据库比大多数人想象得要简单。实际上,你甚至不需要成为一个有经验的程序员就可以使用 SQL 创建数据库。在本文中,我将解释如何使用 MySQL 5.6 来创建简单的关系型数据库管理系统(RDMS)。在开始之前,我想顺便感谢一下 SQL Fiddle,这是我用来运行脚本的工具。它提供了一个用于测试简单脚本的有用的沙箱。

在本教程中,我将构建一个使用如下实体关系图(ERD)中显示的简单架构的数据库。数据库列出了学生和正在学习的课程。为了保持简单,我使用了两个实体(即表),只有一种关系和依赖。这两个实体称为 dbo_studentsdbo_courses

数据库的多样性是一对多的,因为每门课程可以包含很多学生,但每个学生只能学习一门课程。

关于术语的快速说明:

  1. 一张表称为一个实体。
  2. 一个字段称为一个属性。
  3. 一条记录称为一个元组。
  4. 用于构建数据库的脚本称为架构。

构建架构

要构建数据库,使用 CREATE TABLE <表名> 命令,然后定义每个字段的名称和数据类型。数据库使用 VARCHAR(n) (字符串)和 INT(n) (整数),其中 n 表示可以存储的值的长度。例如 INT(2) 可以是 01

这是用于创建两个表的代码:

CREATE TABLE dbo_students
(
  student_id INT(2) AUTO_INCREMENT NOT NULL,
  student_name VARCHAR(50),
  course_studied INT(2),
  PRIMARY KEY (student_id)
);

CREATE TABLE dbo_courses
(
  course_id INT(2) AUTO_INCREMENT NOT NULL,
  course_name VARCHAR(30),
  PRIMARY KEY (course_id)
);

NOT NULL 意味着字段不能为空,AUTO_INCREMENT 意味着当一个新的元组被添加时,ID 号将自动生成,是对先前存储的 ID 号加 1,以强化各实体之间的完整参照性。 PRIMARY KEY 是每个表的惟一标识符属性。这意味着每个元组都有自己的不同的标识。

关系作为一种约束

就目前来看,这两张表格是独立存在的,没有任何联系或关系。要连接它们,必须标识一个外键。在 dbo_students 中,外键是 course_studied,其来源在 dbo_courses 中,意味着该字段被引用。SQL 中的特定命令为 CONSTRAINT,并且将使用另一个名为 ALTER TABLE 的命令添加这种关系,这样即使在架构构建完毕后,也可以编辑表。

以下代码将关系添加到数据库构造脚本中:

ALTER TABLE dbo_students
ADD CONSTRAINT FK_course_studied
FOREIGN KEY (course_studied) REFERENCES dbo_courses(course_id);

使用 CONSTRAINT 命令实际上并不是必要的,但这是一个好习惯,因为它意味着约束可以被命名并且使维护更容易。现在数据库已经完成了,是时候添加一些数据了。

将数据添加到数据库

INSERT INTO <表名> 是用于直接选择要添加哪些属性(即字段)数据的命令。首先声明实体名称,然后声明属性,下边是添加到实体的数据,从而创建一个元组。如果指定了 NOT NULL,这表示该属性不能留空。以下代码将展示如何向表中添加记录:

INSERT INTO dbo_courses(course_id,course_name)
VALUES(001,'Software Engineering');
INSERT INTO dbo_courses(course_id,course_name)
VALUES(002,'Computer Science');
INSERT INTO dbo_courses(course_id,course_name)
VALUES(003,'Computing');

INSERT INTO dbo_students(student_id,student_name,course_studied)
VALUES(001,'student1',001);
INSERT INTO dbo_students(student_id,student_name,course_studied)
VALUES(002,'student2',002);
INSERT INTO dbo_students(student_id,student_name,course_studied)
VALUES(003,'student3',002);
INSERT INTO dbo_students(student_id,student_name,course_studied)
VALUES(004,'student4',003);

现在数据库架构已经完成并添加了数据,现在是时候在数据库上运行查询了。

查询

查询遵循使用以下命令的集合结构:

SELECT <attributes>
FROM <entity>
WHERE <condition>

要显示 dbo_courses 实体内的所有记录并显示课程代码和课程名称,请使用 * 。 这是一个通配符,它消除了键入所有属性名称的需要。(在生产数据库中不建议使用它。)此处查询的代码是:

SELECT *
FROM dbo_courses

此处查询的输出显示表中的所有元组,因此可显示所有可用课程:

| course_id |          course_name |
|-----------|----------------------|
|         1 | Software Engineering |
|         2 |     Computer Science |
|         3 |            Computing |

在后面的文章中,我将使用三种类型的连接之一来解释更复杂的查询:内连接、外连接和交叉连接。

这是完整的脚本:

CREATE TABLE dbo_students
(
  student_id INT(2) AUTO_INCREMENT NOT NULL,
  student_name VARCHAR(50),
  course_studied INT(2),
  PRIMARY KEY (student_id)
);

CREATE TABLE dbo_courses
(
  course_id INT(2) AUTO_INCREMENT NOT NULL,
  course_name VARCHAR(30),
  PRIMARY KEY (course_id)
);

ALTER TABLE dbo_students
ADD CONSTRAINT FK_course_studied
FOREIGN KEY (course_studied) REFERENCES dbo_courses(course_id);

INSERT INTO dbo_courses(course_id,course_name)
VALUES(001,'Software Engineering');
INSERT INTO dbo_courses(course_id,course_name)
VALUES(002,'Computer Science');
INSERT INTO dbo_courses(course_id,course_name)
VALUES(003,'Computing');

INSERT INTO dbo_students(student_id,student_name,course_studied)
VALUES(001,'student1',001);
INSERT INTO dbo_students(student_id,student_name,course_studied)
VALUES(002,'student2',002);
INSERT INTO dbo_students(student_id,student_name,course_studied)
VALUES(003,'student3',002);
INSERT INTO dbo_students(student_id,student_name,course_studied)
VALUES(004,'student4',003);

SELECT *
FROM dbo_courses

学习更多

SQL 并不困难;我认为它比编程简单,并且该语言对于不同的数据库系统是通用的。 请注意,实体关系图中 dbo.<实体> (LCTT 译注:文章中使用的是 dbo_<实体>)不是必需的实体命名约定;我之所以使用,仅仅是因为它是 Microsoft SQL Server 中的标准。

如果你想了解更多,在网络上这方面的最佳指南是 W3Schools.com 中对所有数据库平台的 SQL 综合指南。

请随意使用我的数据库。另外,如果你有任何建议或疑问,请在评论中回复。


via: https://opensource.com/article/18/2/getting-started-sql

作者:Aaron Cocker 译者:MjSeven 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

有一个令人震惊的事实,即人工智能和机器学习的工具和技术在近期迅速兴起。深度学习,或者说“注射了激素的机器学习”,数据科学家和机器学习专家在这个领域有数不胜数等可用的库和框架。很多这样的框架都是基于 Python 的,因为 Python 是一个更通用,相对简单的语言。TheanoKerasTensorFlow 是几个基于 Python 构建的流行的深度学习库,目的是使机器学习专家更轻松。

Google 的 TensorFlow 是一个被广泛使用的机器学习和深度学习框架。 TensorFlow 开源于 2015 年,得到了机器学习专家社区的广泛支持,TensorFlow 已经迅速成长为许多机构根据其机器学习和深度学习等需求而选择的框架。 另一方面,PyTorch 是由 Facebook 最近开发的用于训练神经网络的 Python 包,改编自基于 Lua 的深度学习库 Torch。 PyTorch 是少数可用的深度学习框架之一,它使用 基于磁带的自动梯度系统 tape-based autograd system ,以快速和灵活的方式构建动态神经网络。

在这篇文章中,我们将 PyTorch 与 TensorFlow 进行不同方面的比较。

让我们开始吧!

什么编程语言支持 PyTorch 和 TensorFlow?

虽然主要是用 C++ 和 CUDA 编写的,但 TensorFlow 包含一个位于核心引擎上的 Python API,使得更便于被 Python 支持者 Pythonistas 使用。 除了 Python,它还包括 C++、Haskell、Java、Go 和 Rust 等其他 API,这意味着开发人员可以用他们的首选语言进行编码。

虽然 PyTorch 是一个 Python 软件包,但你也可以提供使用基本的 C/C++ 语言的 API 进行编码。 如果你习惯使用 Lua 编程语言,你也可以使用 Torch API 在 PyTorch 中编写神经网络模型。

PyTorch 和 TensorFlow 有多么易于使用?

如果将 TensorFlow 作为一个独立的框架使用,它可能会有点复杂,并且会给深度学习模型的训练带来一些困难。 为了减少这种复杂性,可以使用位于 TensorFlow 复杂引擎之上的 Keras 封装,以简化深度学习模型的开发和训练。 TensorFlow 也支持 PyTorch 目前没有的分布式培训。 由于包含 Python API,TensorFlow 也可以在生产环境中使用,即可用于培训练和部署企业级深度学习模型。

PyTorch 由于 Torch 的复杂用 Python 重写。 这使得 PyTorch 对于开发人员更为原生。 它有一个易于使用的框架,提供最大化的灵活和速度。 它还允许在训练过程中快速更改代码而不妨碍其性能。 如果你已经有了一些深度学习的经验,并且以前使用过 Torch,那么基于它的速度、效率和易用性,你会更喜欢 PyTorch。 PyTorch 包含定制的 GPU 分配器,这使得深度学习模型具有更高的内存效率。 由此,训练大型深度学习模型变得更容易。 因此,Pytorch 在 Facebook、Twitter、Salesforce 等大型组织广受欢迎。

用 PyTorch 和 TensorFlow 训练深度学习模型

PyTorch 和 TensorFlow 都可以用来建立和训练神经网络模型。

TensorFlow 工作于 SCG(静态计算图)上,包括在模型开始执行之前定义静态图。 但是,一旦开始执行,在模型内的调整更改的唯一方法是使用 tf.session 和 tf.placeholder 张量

PyTorch 非常适合训练 RNN(递归神经网络),因为它们在 PyTorch 中比在 TensorFlow 中运行得更快。 它适用于 DCG(动态计算图),可以随时在模型中定义和更改。 在 DCG 中,每个模块可以单独调试,这使得神经网络的训练更简单。

TensorFlow 最近提出了 TensorFlow Fold,这是一个旨在创建 TensorFlow 模型的库,用于处理结构化数据。 像 PyTorch 一样,它实现了 DCG,在 CPU 上提供高达 10 倍的计算速度,在 GPU 上提供超过 100 倍的计算速度! 在 Dynamic Batching 的帮助下,你现在可以执行尺寸和结构都不相同的深度学习模型。

GPU 和 CPU 优化的比较

TensorFlow 的编译时间比 PyTorch 短,为构建真实世界的应用程序提供了灵活性。 它可以从 CPU、GPU、TPU、移动设备到 Raspberry Pi(物联网设备)等各种处理器上运行。

另一方面,PyTorch 包括 张量 tensor 计算,可以使用 GPU 将深度神经网络模型加速到 50 倍或更多。 这些张量可以停留在 CPU 或 GPU 上。 CPU 和 GPU 都是独立的库, 无论神经网络大小如何,PyTorch 都可以高效地利用。

社区支持

TensorFlow 是当今最流行的深度学习框架之一,由此也给它带来了庞大的社区支持。 它有很好的文档和一套详细的在线教程。 TensorFlow 还包括许多预先训练过的模型,这些模型托管和提供于 GitHub。 这些模型提供给热衷于使用 TensorFlow 开发者和研究人员一些现成的材料来节省他们的时间和精力。

另一方面,PyTorch 的社区相对较小,因为它最近才发展起来。 与 TensorFlow 相比,文档并不是很好,代码也不是很容易获得。 然而,PyTorch 确实允许个人与他人分享他们的预训练模型。

PyTorch 和 TensorFlow —— 力量悬殊的故事

就目前而言,由于各种原因,TensorFlow 显然比 PyTorch 更受青睐。

TensorFlow 很大,经验丰富,最适合实际应用。 是大多数机器学习和深度学习专家明显的选择,因为它提供了大量的功能,最重要的是它在市场上的成熟应用。 它具有更好的社区支持以及多语言 API 可用。 它有一个很好的文档库,由于从准备到使用的代码使之易于生产。 因此,它更适合想要开始深度学习的人,或者希望开发深度学习模型的组织。

虽然 PyTorch 相对较新,社区较小,但它速度快,效率高。 总之,它给你所有的优势在于 Python 的有用性和易用性。 由于其效率和速度,对于基于研究的小型项目来说,这是一个很好的选择。 如前所述,Facebook、Twitter 等公司正在使用 PyTorch 来训练深度学习模型。 但是,使用它尚未成为主流。 PyTorch 的潜力是显而易见的,但它还没有准备好去挑战这个 TensorFlow 野兽。 然而,考虑到它的增长,PyTorch 进一步优化并提供更多功能的日子并不遥远,直到与 TensorFlow可以 比较。

作者: Savia Lobo,非常喜欢数据科学。 喜欢更新世界各地的科技事件。 喜欢歌唱和创作歌曲。 相信才智上的艺术。


via: https://datahub.packtpub.com/deep-learning/dl-wars-pytorch-vs-tensorflow/

作者:Savia Lobo 译者:Wuod3n 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出