Linux/Unix 进阶

Author Avatar
Tr0y 10月 08, 2018 16:13:07 本文共 8.8k 字
  • 文为知己者书
  • 在其它设备中阅读本文章

记录一下遇到的 Linux/Unix 各种命令、报错解决、知识与技巧。

配置一个顺手的渗透虚拟机/服务器

传送门

键盘党的自豪

传送门

报错解决

bash: 无法设定终端进程组

ssh -T user@202.101.172.35 /bin/bash -i 的时候发现 bash: 无法设定终端进程组 (-1): 对设备不适当的 ioctl 操作。bash: 此 shell 中无任务控制

解决:暂无方案。不过似乎不影响使用。

msfconsole 报内存不够

安装 msf 后启动 msfconsole 报错:

/opt/metasploit-framework/embedded/lib/ruby/gems/2.4.0/gems/activesupport-4.2.10/lib/active_support/core_ext/kernel/agnostics.rb:7:in ``': Cannot allocate memory - infocmp (Errno::ENOMEM)

解决:增加 swap 分区文件大小即可:

# 以下命令默认为 root 用户

> free -m # 查看内存状态

              total        used        free      shared  buff/cache   available
Mem:            992         189          79          13         722         614
Swap:             0           0           0
# Swap 也就是虚拟内存,为 0

# 选择一个较大的分区,建立分区文件
> dd if=/dev/zero of=/opt/swap bs=1024 count=1024000
1024000+0 records in
1024000+0 records out
1048576000 bytes (1.0 GB) copied, 16.6877 s, 62.8 MB/s
# 该命令表示在 opt 分区建立名为 swap,大小为 1G 的虚拟内存文件

# 将 swap 文件设置为 swap 分区文件
# 更改 swap 文件的权限
> chmod 600 /opt/swap

> mkswap /opt/swap # 格式化 swap 分区
Setting up swapspace version 1, size = 1023996 KiB
no label, UUID=fc47f29e-31af-401e-856d-0fec5262179e

# 激活swap,启用分区交换文件
> swapon /opt/swap

# 现在看下结果
> free -m
              total        used        free      shared  buff/cache   available
Mem:            992         191          63          13         737         625
Swap:           999           0         999

# 将分区设置为开机自动挂载
> vim /etc/fstab

# 增加
/opt/swap           swap                    swap    defaults        0 0

再次启动 msfconsole 即可。(不够大可增加 swap)

卸载 swap 分区:

# 首先停止swap分区
> swapoff /opt/swap

# 删除掉swap文件即可
> rm -rf /opt/swap

ubuntu 使用 apt 的时候报 Py3 错误

报错:

正在设置 ssh-import-id (5.7-0ubuntu1) ...
Traceback (most recent call last):
  File "/usr/bin/py3compile", line 290, in <module>
    main()
  File "/usr/bin/py3compile", line 270, in main
    options.force, options.optimize, e_patterns)
  File "/usr/bin/py3compile", line 156, in compile
    cfn = interpreter.cache_file(fn, version)
  File "/usr/share/python3/debpython/interpreter.py", line 212, in cache_file
    (fname[:-3], self.magic_tag(version), last_char))
  File "/usr/share/python3/debpython/interpreter.py", line 246, in magic_tag
    return self._execute('import imp; print(imp.get_tag())', version)
  File "/usr/share/python3/debpython/interpreter.py", line 359, in _execute
    raise Exception('{} failed with status code {}'.format(command, output['returncode']))
Exception: python3.6 -c 'import imp; print(imp.get_tag())' failed with status code 127
dpkg: 处理软件包 ssh-import-id (--configure)时出错:
 installed ssh-import-id package post-installation script subprocess returned error exit status 1
在处理时有错误发生:
 ssh-import-id
E: Sub-process /usr/bin/dpkg returned an error code (1)

常出现与安装 pyenv 的机器。

修复:
pyenv global 3.6.5 # 改为自己安装的版本

zsh sudo alias not found 问题

假如你在 .zshrc 里定义了一个 alias:alias c=clear,你会发现,sudo c 的时候会报错(zsh: command not found: c),这时候欺骗一下 zsh 即可:
alias sudo='sudo '

GLIBC_2.18’ not found

报错:”/lib64/libc.so.6: version `GLIBC_2.18’ not found (required by /lib64/libstdc++.so.6)”

解决:

curl -O http://ftp.gnu.org/gnu/glibc/glibc-2.18.tar.gz
tar zxf glibc-2.18.tar.gz 
cd glibc-2.18/
mkdir build
cd build/
../configure --prefix=/usr
make -j2
make install

慢慢的

zsh tab 出现重叠问题

按下 tab 补全的时候,会出现类似这样的问题:
mvmv xxx xxx

出现2个重叠的 mv,我猜测是因为 unicode 的原因。在 .zshrc 中加入:

export LC_ALL=en_US.UTF-8  
export LANG=en_US.UTF-8

即可

screen 出现乱码

~ 下新建 .screenrc,写入:

defutf8 on
defencoding utf8
encoding UTF-8 UTF-8

注意,修改后只对之后新建的 screen 生效。

知识与技巧

获取自己 ip 的方法

  • 内网

    1. 可能会有多个 ip(比如 127.0.0.1 等等),结果用空格隔开
      ifconfig | grep -A 1 "inet" | grep netmask | cut -d " " -f 2 | tr "\n" " "
    2. 只有那个真正的内网 ip(不需要联网)
      python -c "import socket;print(socket.gethostbyname(socket.gethostname()))"
    3. 只有那个真正的内网 ip(需要联网)
      python -c "import socket;print([(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1])"

      通常 2 与 3 结合使用,利用 cmd1||cmd2 执行 cmd1 不成功时,执行 cmd2

      python -c "import socket;print([(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1])"||python -c "import socket;print(socket.gethostbyname(socket.gethostname()))"
      
  • 外网
    当 {query} 为空时,就是自己的 ip,不为空时,则查询指定 ip/域名 的信息 curl --silent ip.cn/index.php?ip={query}

Unix/Linux 终端控制字符

\033[0m                 关闭所有属性
\033[1m                 设置高亮度
\033[4m                 下划线
\033[5m                 闪烁
\033[7m                 反显
\033[8m                 消隐
\033[30m -- \033[37m    设置前景色
\033[40m -- \033[47m    设置背景色
\033[nA                 光标上移 n 行
\033[nB                 光标下移 n 行
\033[nC                 光标右移 n 列
\033[nD                 光标左移 n 列
\033[y;H                设置光标位置
\033[2J                 清屏(不彻底)
\033c                   清屏(彻底)
\033[K                  清除从光标到行尾的内容
\033[s                  保存光标位置
\033[u                  恢复光标位置
\033[?25l               隐藏光标
\033[?25h               显示光标

在 mac 的 iterm2 下,彻底清空终端为:printf "\e]50;ClearScrollback\a"
为了保证 Linux 与 Unix 都可用,最好这样:printf '\033c\e]50;ClearScrollback\a'

获得终端的大小

echo $LINES
echo $COLUMNS

有用的 .zshrc 函数

打开 ~/.zshrc,写入函数,然后 source ~/.zshrc,即可使用

在 mac 下利用 terminal-notifier 发起通知

function notify(){
    start_time=`date +%s`;
    cmd=`echo $@`;
    eval $@;
    end_time=`date +%s`
    timer_time=$((end_time-start_time))
    unit="s"

    if [[ $timer_time -gt 60 ]]; then
        unit="m"
        timer_time=`echo $(($timer_time/60.0))|awk '{printf("%.2f", $1)}'`
    fi

    terminal-notifier -title 'Notifier' -message 'command was finished in '${timer_time}${unit}'
'${cmd} -sound default -execute "open /Applications/iTerm.app";
}

使用方式为:

# 单个命令
notify curl baidu.com
# 或
notify "curl baidu.com"

# 多个命令要用引号包起来
notify "curl baidu.com; curl tr0y.wang"

通知结果

无需参数解压任意压缩文件

function x {
 if [ -z "$1" ]; then
    echo "Usage: extract <path/file_name>.<zip|rar|bz2|gz|tar|tbz2|tgz|Z|7z|xz|ex|tar.bz2|tar.gz|tar.xz>"
    echo "       extract <path/file_name_1.ext> [path/file_name_2.ext] [path/file_name_3.ext]"
 else
    for n in "$@"
    do
      if [ -f "$n" ] ; then
          case "${n%,}" in
            *.cbt|*.tar.bz2|*.tar.gz|*.tar.xz|*.tbz2|*.tgz|*.txz|*.tar)
                         tar xvf "$n"       ;;
            *.lzma)      unlzma ./"$n"      ;;
            *.bz2)       bunzip2 ./"$n"     ;;
            *.cbr|*.rar)       unrar x -ad ./"$n" ;;
            *.gz)        gunzip ./"$n"      ;;
            *.cbz|*.epub|*.zip)       unzip ./"$n"       ;;
            *.z)         uncompress ./"$n"  ;;
            *.7z|*.arj|*.cab|*.cb7|*.chm|*.deb|*.dmg|*.iso|*.lzh|*.msi|*.pkg|*.rpm|*.udf|*.wim|*.xar)
                         7z x ./"$n"        ;;
            *.xz)        unxz ./"$n"        ;;
            *.exe)       cabextract ./"$n"  ;;
            *.cpio)      cpio -id < ./"$n"  ;;
            *.cba|*.ace)      unace x ./"$n"      ;;
            *)
                         echo "extract: '$n' - unknown archive method"
                         return 1
                         ;;
          esac
      else
          echo "'$n' - file does not exist"
          return 1
      fi
    done
fi
}

使用方式为:
x test.zip 等等…

服务器完成命令反馈

需要购买 pushover 的服务

function notify(){
    start_time=`date +%s`;
    cmd=`echo $@`;
    eval $@;
    end_time=`date +%s`

    timer_time=$((end_time-start_time))
    unit="s"

    if [[ $timer_time -gt 60 ]]; then
        unit="m"
        timer_time=`echo $(($timer_time/60.0))|awk '{printf("%.2f", $1)}'`
    fi

    pushover --user-key XXXXXXXXXX --api-token XXXXXXXXXX --title "Tencent's job" 'command was finished in '${timer_time}${unit}'
'${cmd}
}

反馈的结果与 mac 下的那个 notify 函数类似(看一下上面)。

有用的 .vimrc 参数

  • 语法高亮:syntax on
  • 打开文件时,光标自动恢复到上一次的位置
    if has("autocmd")
    au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif
    endif
    
  • 显示行号:set nu!

w 命令

用来查看登录者的信息及他们的行为。

  • 常用参数:
    • -h 不显示标题。
  • 格式
    • USER:登录用户名
    • TTY:登录后系统分配的终端号
    • FROM:远程主机名,即从哪登录的
    • LOGIN@:何时登录
    • IDLE:用户空闲时间。这是个计时器,一旦用户执行任何操作,改计时器就会被重置。
    • WHAT:当前正在运行进程的命令行

让 w 查不到登录信息

  1. Rootkit(接受、反弹 shell 等等)
  2. 把远程的 bash 映射到本地:ssh -T username@ip "/bin/sh -i"
  3. sftp

Rootkit

Rootkit —— 持久并毫无察觉地驻留在目标计算机中,对系统进行操纵、并通过隐秘渠道收集数据的程序。Rootkit 的三要素就是:隐藏、操纵、收集数据。改系统调用,比如修改 ls、netstat 等,这种替换掉系统原有的普通命令,换成自己特殊目的的可执行文件,属于 rootkit 的核心。

ioctl

ioctl 是设备驱动程序中对设备的 I/O 通道进行管理的函数。所谓对 I/O 通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。

ssh -T

禁止分配伪终端。当用 ssh 或 telnet 等登录系统时,系统分配给我们的终端就是伪终端。
如果 ssh 使用此选项登录系统时,由于禁用,将无法获得终端;但仍能够获得 shell,只不过看起来像在本地,也没有很多应有的环境变量,例如命令提示符,PS1 等。
当使用命令 ps -ef|grep bash 时看到 root 23664 23662 0 19:31 ? 00:00:00 /bin/bash -i 显示终端那里是一个问号。

PS1

PS1 是 Linux 终端用户的一个环境变量,用来定义命令行提示符的参数。即 > 或者 # 这个符号的相关参数。

pkill

是 ps 命令和 kill 命令的结合,按照进程名来杀死指定进程,pkill 和 killall 应用方法差不多,也是直接杀死运行中的程序;如果想杀掉单个进程,请用 kill 来杀掉。

  • 常用参数

    • -e:输出 kill 了啥
    • -c:返回匹配的数量
  • 常用方法

    • 将用户踢下线:pkill -9 -t pts/1

tty(n) 与 pts/(n)

tty(n)

控制终端,可以用 Ctrl+Alt+F1-F(n) 切换

pts/(n)

伪终端。位于 /dev/pts/n。pts(pseudo-terminal slave) 是 pty 的实现方法,与 ptmx(pseudo-terminal master) 配合使用实现 pty。pty(pseudo terminal device)由两部分构成,ptmx 是 master 端,pts 是 slave 端。pts 也是 tty 设备

TTY 和 PTS 的区别
对用户空间的程序来说,他们没有区别,都是一样的;从内核里面来看,pts 的另一端连接的是 ptmx,而 tty 的另一端连接的是内核的终端模拟器,ptmx 和终端模拟器都只是负责维护会话和转发数据包;再看看 ptmx 和内核终端模拟器的另一端,ptmx 的另一端连接的是用户空间的应用程序,如 sshd、tmux 等,而内核终端模拟器的另一端连接的是具体的硬件,如键盘和显示器。

可以 echo "test">/dev/pts/3 向 pts/3 这个伪终端写入数据

tty 也是一个命令,可以列出当前的终端机连接标准输入设备的文件名称。

一篇好文章:Linux TTY/PTS 概述

tail

通俗讲来,就是把某个档案文件的最后几行显示到终端上,假设该档案有更新,tail 会自己主动刷新,确保你看到最新的档案内容。

  • 常用参数
    • -f:该参数用于监视 File 文件增长。
    • -c:Number 从 Number 字节位置读取指定文件
    • -n:Number 从 Number 行位置读取指定文件。
    • -m:Number 从 Number 多字节字符位置读取指定文件,比方你的文件假设包括中文字,假设定 -c 参数,可能导致截断,但使用 -m 则会避免该问题。
    • -b:Number 从 Number 表示的 512 字节块位置读取指定文件。
    • -k:Number 从 Number 表示的 1KB 块位置读取指定文件。
    • r:逆序

扩展知识:

  • tail -f 的时候可以按 ctrl+s 来暂停输出,按 ctrl+q 恢复。
  • tail -f:等同于 –follow=descriptor,根据文件描述符进行追踪,当文件改名或被删除,追踪停止。
  • tail -F:等同于 –follow=name –retry,根据文件名进行追踪,并保持重试,即该文件被删除或改名后,如果再次创建相同的文件名,会继续追踪
  • tailf:等同于 tail -f -n 10(貌似 tail -f 或 -F 默认也是打印最后 10 行,然后追踪文件),与 tail -f 不同的是,如果文件不增长,它不会去访问磁盘文件,所以 tailf 特别适合那些便携机上跟踪日志文件,因为它减少了磁盘访问,可以省电

ctrl+d

不是发送信号,而是表示一个特殊的二进制值,表示 EOF。

扩展知识:

ctrl+c 和 ctrl+z 都是中断命令,但是他们的作用却不一样.
ctrl+c 是强制中断程序的执行,进程已经终止。
ctrl+z 的是将任务中止(暂停的意思),但是此任务并没有结束,他仍然在进程中他只是维持挂起的状态,用户可以使用 fg/bg 操作继续前台或后台的任务,fg 命令重新启动前台被中断的任务,bg 命令把被中断的任务放在后台执行(bg:将一个在后台暂停的命令,变成在后台执行继续执行)。
ctrl+d 不是发送信号,而是表示一个特殊的二进制值,表示 EOF。
注:在 shell 中,ctrl+d 表示退出当前 shell。

Linux shell 单引号和双引号

共同点:界定一个字符串
不同点如下

  • 单引号属于 强引用,它会忽略所有被引起来的字符的特殊处理,被引用起来的字符会被原封不动的使用,唯一需要注意的点是不允许引用自身。
  • 双引号属于 弱引用,它会对一些被引起来的字符进行特殊处理,主要包括以下情况:
    • $ 加变量名可以取变量的值,比如:
      » url="www.tr0y.wang"
      » echo '$url'
      $url
      » echo "$url"
      www.tr0y.wang
      
    • 反引号(`) 和 $() 引起来的字符会被当做命令执行后替换原来的字符:
      » echo '$(echo www.tr0y.wang)'
      $(echo www.tr0y.wang)
      » echo "$(echo www.tr0y.wang)"
      www.tr0y.wang
      
      » echo '`echo www.tr0y.wang`'
      `echo www.tr0y.wang`
      » echo "`echo www.tr0y.wang`"
      www.tr0y.wang
      
  • 当需要在单引号里使用特殊字符($, `, “, \)时必须进行转义,也就是在前面加 \

screen 滚动问题

vim /etc/screenrc 增加2行:

defscrollback 100000
bind / eval "scrollback 0" "scrollback 15000"

ctrl+a,再按 esc 进入滚动模式,然后用滚轮或者箭头即可看输出的历史。
如果要清空历史记录,则为按 ctrl+a,再按 /

修改 ipython 配色

ipython profile create # 新建配置文件
vim ~/.ipython/profile_default/ipython_config.py # 修改配置

找到

## Set the color scheme (NoColor, Neutral, Linux, or LightBG).
c.InteractiveShell.colors = 'Neutral'

Neutral 改为 Linux 即可(适合深色背景)。
对比效果如下:

设置 zsh 不记录错误的历史命令

建议服务器不要开启
在 .zshrc 写入:
zshaddhistory() { whence ${${(z)1}[1]} >| /dev/null || return 1 }
即可

Linux / 下中各个文件夹的作用

  • /:根目录;包含了所有的文件目录

    相当于中央系统。

  • /boot:引导程序,内核等存放的目录;这个目录,包括了在引导过程中所必需的文件

    在最开始的启动阶段,通过引导程序将内核加载到内存,完成内核的启动(这个时候,虚拟文件系统还不存在,加载的内核虽然是从硬盘读取的,但是没经过 Linux 的虚拟文件系统,是通过比较底层的东西来实现的。然后内核自己创建好虚拟文件系统,并且从虚拟文件系统的其他子目录中(例如 /sbin 和 /etc 加载需要在开机启动的其他程序或者服务或者特定的动作(部分可以由用户自己在相应的目录中修改相应的文件来配制。如果我们的机器中包含多个操作系统,那么可以通过修改这个目录中的某个配置文件(例如 grub.conf 来调整启动的默认操作系统,系统启动的择菜单,以及启动延迟等参数。

  • /sbin:超级用户可以使用的命令的存放目录

    存放大多涉及系统管理的命令(例如引导系统的 init 程序),是超级权限用户 root 的可执行命令存放地,普通用户无权限执行这个目录下的命令(但是有时普通用户也可能会用到)。我们要记住,凡是目录 sbin 中包含的都是属于 root 用户的。

  • /bin:普通用户可以使用的命令的存放目录

    系统所需要的那些命令位于此目录,比如 ls、cp、mkdir 等命令;类似的目录还有 /usr/bin,/usr/local/bin 等等。这个目录中的文件都是可执行的、普通用户都可以使用的命令。作为基础系统所需要的最基础的命令就是放在这里的。

  • /lib:根目录下的所有程序的共享库目录

    此目录下包含系统引导和在根用户执行命令时候所必需用到的共享库。做个不太好但是比较形象的比喻,有点类似于 Windows 上面的 system32 目录。按理说,这里存放的文件应该是 /bin 目录下程序所需要的库文件的存放地,也不排除一些例外的情况。类似的目录还有 /usr/lib,/usr/local/lib 等等。

  • /dev:设备文件目录

    在 Linux 中设备都是以文件形式出现,这里的设备可以是硬盘,键盘,鼠标,网卡,终端等设备,通过访问这些文件可以访问到相应的设备。设备文件可以使用 mknod 命令来创建;而为了将对这些设备文件的访问转化为对设备的访问,需要向相应的设备提供设备驱动模块(一般将设备驱动编译之后,生成的结果是一个 *.ko 类型的二进制文件,在内核启动之后,再通过 insmod 等命令加载相应的设备驱动之后,我们就可以通过设备文件来访问设备了。一般来说,想要 Linux 系统支持某个设备,需要相应的硬件设备,支持硬件的驱动模块,以及相应的设备文件。

  • /home:普通用户的家目录

    在 Linux 机器上,用户主目录通常直接或间接地放在此目录下,其结构通常由管理员来决定。通常而言,系统的每个用户都自己的家目录,目录以用户名作为名字存放在 /home 下面(例如 tr0y 用户,其家目录的名字为 /home/tr0y。该目录中保存了绝大多数的用户文件(用户自己的配置文件,定制文件,文档,数据等)。

  • /root:用户 root 的 HOME 目录

    系统管理员(就是 root 用户或超级用户)的主目录比较特殊,不存放在 /home 中,而是直接放在 /root 目录下了。

  • /etc:全局的配置文件存放目录

    系统和程序一般都可以通过修改相应的配置文件,来进行配置。例如,要配置系统开机的时候启动那些程序,配置某个程序启动的时候显示什么样的风格等等。通常这些配置文件都集中存放在 /etc 目录中,所以想要配置什么东西的话,可以在 /etc 下面寻找我们可能需要修改的文件。

  • /usr:这个目录中包含了命令库文件和在通常操作中不会修改的文件

    这个目录对于系统来说也是一个非常重要的目录,其地位类似 Windows 上面的 Program Files 目录(安装程序的时候,默认就是安装在此文件内部某个子文件夹内。输入命令后系统默认执行 /usr/bin 下的程序(当然,前提是这个目录的路径已经被添加到了系统的环境变量中。此目录通常也会挂载一个独立的磁盘分区,它应保存共享只读类文件,这样它可以被运行 Linux 的不同主机挂载。

  • /proc:特殊文件目录

    这个目录采用一种特殊的文件系统格式(proc 格式,内核支持这种格式。其中包含了全部虚拟文件。它们并不保存在磁盘中,也不占据磁盘空间(尽管命令 ls -c 会显示它们的大小)。当你查看它们时,实际上看到的是内存里的信息,这些文件助于我们了解系统内部信息。例如:

    • 1/ 关于进程 1 的信息目录。每个进程在 /proc 下一个名为其进程号的目录。
    • cpuinfo 处理器信息,如类型、制造商、型号和性能。
    • meminfo 存储器使用信息,包括物理内存和swap。
    • net 网络协议状态信息。
    • version 核心版本。
  • /opt:可选择的文件目录

    这个目录表示的是可选择的意思,一些自定义软件包或者第三方工具,就可以安装在这里。

  • /mnt:临时挂载目录

    这个目录一般是用于存放挂载储存设备的挂载目录的。比如磁盘,光驱,网络文件系统等。当我们需要挂载某个磁盘设备的时候,可以把磁盘设备挂载到这个目录上去,这样我们可以直接通过访问这个目录来访问那个磁盘了。一般来说,我们最好在 /mnt 目录下面多建立几个子目录,挂载的时候挂载到这些子目录上面,因为通常我们可能不仅仅是挂载一个设备。

  • /media:挂载的媒体设备目录

    挂载的媒体设备目录,一般外部设备挂载到这里,例如 cdrom 等。比如我们插入一个 U 盘,我们一般会发现,Linux 自动在这个目录下建立一个 disk 目录,然后把 U 盘挂载到这个 disk 目录上,通过访问这个 disk 来访问 U 盘。

  • /var:内容经常变化的目录

    此目录下文件的大小可能会改变,如缓冲文件,日志文件,缓存文件,等一般都存放在这里。

  • /tmp:临时文件目录

    该目录存放系统中的一些临时文件,文件可能会被系统自动清空。

  • /lost+found:恢复文件存放的位置

    当系统崩溃的时候,在系统修复过程中需要恢复的文件,可能就会在这里被找到了,这个目录一般为空。

/etc/passwd 和 /etc/shadow

合理的命名应该是:
/etc/passwd => /etc/users
/etc/shadow => /etc/password

  • /etc/passwd 文件中的每个用户都有一个对应的记录行,记录着这个用户的基本属性。该文件对所有用户可读。不含密码信息。
  • /etc/shadow 文件正如他的名字一样,他是 passwd 文件的一个影子,/etc/shadow 文件中的记录行与 /etc/passwd 中的一一对应,它由 pwconv 命令根据 /etc/passwd 中的数据自动产生。但是 /etc/shadow 文件只有系统管理员才能够进行修改和查看。含有密码信息。

/etc/passwd 中一行记录对应着一个用户,每行记录又被冒号(:)分隔为 7 个字段,其格式和具体含义如下:

用户名 : 口令 : 用户标识号 : 组标识号 : 注释性描述 : 主目录 : 登录 Shell

  • 用户名 (login_name):是代表用户账号的字符串。通常长度不超过 8 个字符,并且由大小写字母、/ 或数字组成。登录名中不能有冒号(:),因为冒号在这里是分隔符。为了兼容起见,登录名中最好不要包含点字符(.),并且不使用连字符(-)和加号(+)打头。
  • 口令(passwd):一些系统中,存放着加密后的用户口令。虽然这个字段存放的只是用户口令的加密串,不是明文,但是由于 /etc/passwd 文件对所有用户都可读,所以这仍是一个安全隐患。因此,现在许多 Linux 系统都使用了 shadow 技术,把真正的加密后的用户口令字存放到 /etc/shadow 文件中,而在 /etc/passwd 文件的口令字段中只存放一个特殊的字符,例如 x 或者 *
  • 用户标识号(UID):是一个整数,系统内部用它来标识用户。一般情况下它与用户名是一一对应的。如果几个用户名对应的用户标识号是一样的,系统内部将把它们视为同一个用户,但是它们可以有不同的口令、不同的主目录以及不同的登录 Shell 等。取值范围是 0-65535。0 是超级用户 root 的标识号,1-99 由系统保留,作为管理账号,普通用户的标识号从 100 开始。在 Linux 系统中,这个界限是 500。
  • 组标识号(GID):字段记录的是用户所属的用户组。它对应着 /etc/group 文件中的一条记录。
  • 注释性描述(users):字段记录着用户的一些个人情况,例如用户的真实姓名、电话、地址等,这个字段并没有什么实际的用途。在不同的 Linux 系统中,这个字段的格式并没有统一。在许多 Linux 系统中,这个字段存放的是一段任意的注释性描述文字,用做 finger 命令的输出。
  • 主目录(home_directory):也就是用户的起始工作目录,它是用户在登录到系统之后所处的目录。在大多数系统中,各用户的主目录都被组织在同一个特定的目录下,而用户主目录的名称就是该用户的登录名。各用户对自己的主目录有读、写、执行(搜索)权限,其他用户对此目录的访问权限则根据具体情况设置。
  • 登录 Shell(Shell):用户登录后,要启动一个进程,负责将用户的操作传给内核,这个进程是用户登录到系统后运行的命令解释器或某个特定的程序,即 Shell。Shell 是用户与 Linux 系统之间的接口。Linux 的Shell 有许多种,每种都有不同的特点。常用的有 sh(BourneShell),csh(CShell),ksh(KornShell),tcsh(TENEX/TOPS-20typeCShell),bash(BourneAgainShell) 等。系统管理员可以根据系统情况和用户习惯为用户指定某个 Shell。如果不指定 Shell,那么系统使用 sh 为默认的登录 Shell,即这个字段的值为 /bin/sh。

/etc/shadow 文件格式与 /etc/passwd 文件格式类似,同样由若干个字段组成,字段之间用 : 隔开:

登录名 : 加密口令 : 最后一次修改时间 : 最小时间间隔 : 最大时间间隔 : 警告时间 : 不活动时间 : 失效时间 : 标志

  • 登录名:与 /etc/passwd 文件中的登录名相一致的用户账号
  • 口令:存放的是加密后的用户口令字。
    • 为空,则对应用户没有口令,登录时不需要口令;
    • 星(*)号代表帐号被锁定;
    • 双叹号(!!)表示这个密码已经过期了;
    • $6$ 开头的,表明是用 SHA-512 加密;
    • $1$ 表明是用 MD5 加密;
    • $2$ 是用 Blowfish 加密;
    • $5$ 是用 SHA-256 加密;
  • 最后一次修改时间:表示的是从某个时刻起,到用户最后一次修改口令时的天数。时间起点对不同的系统可能不一样。例如在 SCOLinux 中,这个时间起点是 1970 年 1 月 1 日。
  • 最小时间间隔:指的是两次修改口令之间所需的最小天数。
  • 最大时间间隔:指的是口令保持有效的最大天数。
  • 警告时间:字段表示的是从系统开始警告用户到用户密码正式失效之间的天数。
  • 不活动时间:表示的是用户没有登录活动但账号仍能保持有效的最大天数。
  • 失效时间:字段给出的是一个绝对的天数,如果使用了这个字段,那么就给出相应账号的生存期。期满后,该账号就不再是一个合法的账号,也就不能再用来登录了。

Linux 下重要日志文件

  • /var/log/boot.log

    该文件记录了系统在引导过程中发生的事件,就是 Linux 系统开机自检过程显示的信息。

  • /var/log/cron

    该日志文件记录 crontab 守护进程 crond 所派生的子进程的动作,前面加上用户、登录时间和 PID,以及派生出的进程的动作。CMD 的一个动作是 cron 派生出一个调度进程的常见情况。REPLACE(替换)动作记录用户对它的 cron 文件的更新,该文件列出了要周期性执行的任务调度。RELOAD 动作在 REPLACE 动作后不久发生,这意味着 cron 注意到一个用户的 cron 文件被更新而 cron 需要把它重新装入内存。该文件可能会查到一些反常的情况。

  • /var/log/syslog

    默认 centos 不生成该日志文件,但可以配置 /etc/syslog.conf 让系统生成该日志文件。它和 /etc/log/messages 日志文件不同,它只记录警告信息,常常是系统出问题的信息,所以更应该关注该文件。要让系统生成该日志文件,在 /etc/syslog.conf 文件中加上:*.warning /var/log/syslog 该日志文件能记录当用户登录时 login 记录下的错误口令、Sendmail 的问题、su 命令执行失败等信息。

  • /var/log/secure

    该日志文件记录与安全相关的信息。

  • /var/log/lastlog

    该日志文件记录最近成功登录的事件和最后一次不成功的登录事件,由 login 生成。在每次用户登录时被查询,该文件是二进制文件,需要使用 lastlog 命令查看,根据 UID 排序显示登录名、端口号和上次登录时间。如果某用户从来没有登录过,就显示为 **Never logged in**。该命令只能以 root 权限执行。

  • /var/log/wtmp

    该日志文件永久记录每个用户登录、注销及系统的启动、停机的事件。因此随着系统正常运行时间的增加,该文件的大小也会越来越大,增加的速度取决于系统用户登录的次数。该日志文件可以用来查看用户的登录记录,last 命令就通过访问这个文件获得这些信息,并以反序从后向前显示用户的登录记录,last 也能根据用户、终端 tty 或时间显示相应的记录。

    命令last有两个可选参数:
    last -u 用户名:显示用户上次登录的情况。
    last -t 天数:显示指定天数之前的用户登录情况

  • /var/run/utmp

    该日志文件记录有关当前登录的每个用户的信息。因此这个文件会随着用户登录和注销系 统而不断变化,它只保留当时联机的用户记录,不会为用户保留永久的记录。系统中需要查询当前用户状态的程序,如 who、w、users、finger 等就需要访问这个文件。该日志文件并不能包括所有精确的信息,因为某些突发错误会终止用户登录会话,而系统没有及时 更新 utmp 记录,因此该日志文件的记录不是百分之百值得信赖的。

  • /var/log/btmp

    记录失败的登录尝试。被 lastb 命令用来记录最后失败的登录尝试的列表。

以上提及的 4 个文件(/var/log/wtmp、/var/run/utmp、 /var/log/lastlog、/var/log/btmp)是日志子系统的关键文件,都记录了用户登录的情况。这些文件的所有记录都包含了时间戳。这些文件是按二进制保存的,故不能用 less、cat 之类的命令直接查看这些文件,而是需要使用相关命令通过这些文件而查看。其中,btmp、utmp 和 wtmp 文件的数据结构是一样的,而 lastlog 文件则使用另外的数据结构,关于它们的具体的数据结构可以使用 man 命令查询。

每次有一个用户登录时,login 程序在文件 lastlog 中查看用户的 UID。如果存在,则把用户上次登录、注销时间和主机名写到标准输出中,然后 login 程序在 lastlog 中记录新的登录时间,打开 utmp 文件并插入用户的 utmp 记录。该记录一直用到用户登录退出时删除。utmp 文件被各种命令使用,包括 who、w、users 和 finger。下一步,login 程序打开文件 wtmp 附加用户的 utmp 记录。当用户登录退出时,具有更新时间戳的同一 utmp 记录附加到文件中。wtmp 文件被程序 last 使用。

对待日志的原则:日志并不完全可靠
需要注意的地方:

  • 用户在非常规的时间登录
  • 不正常的日志记录,比如日志的残缺不全或者是诸如 wtmp 这样的日志文件无故地缺少了中间的记录文件
  • 用户登录系统的IP地址和以往的不一样
  • 用户登录失败的日志记录,尤其是那些一再连续尝试进入失败的日志记录
  • 非法使用或不正当使用超级用户权限 su 的指令
  • 无故或者非法重新启动各项网络服务的记录

Linux 隐藏痕迹

  • 不记录 shell 的历史命令(在 .bash_history.zsh_history 等中不会显示)
    unset HISTORY HISTFILE HISTSAVE HISTZONE  HISTLOG;
    export HISTFILE=/dev/null;
    export HISTSIZE=0;
    export HISTFILESIZE=0
    
  • 使得 w 命令无法看到在线信息:LLC,即修改 /var/run/utmp 中的记录。或者参考疑问链第一周记录的办法。

Linux 抹去痕迹

  • 利用 utmpdump 修改 /var/log/wtmp 文件(即修改 last 命令的结果)。如修改登录 ip:
    utmpdump /var/log/wtmp | sed "s/[原 ip]/[修改后的 ip]/g" | utmpdump -r > /tmp/wtmp1;
    mv /tmp/wtmp1 /var/log/wtmp
    
  • 修改文件的 atime, mtime
  • 利用 LLC

xargs 教程

一篇好文章

  • 常用参数:
    • 利用 -i 参数以自定义参数位置。
    • -P: 多进程处理

持续化查看

假如我们有一个后台命令:ping baidu.com > tmp &。我们想要持续查看输出,要怎么办呢?

  • tail -f tmp
  • watch -n 1 'cat tmp|tail -n 5'

End

What do you think?

本文标题: Linux/Unix 进阶
原始链接: http://www.tr0y.wang/2018/10/08/LUinux/
发布时间: 2018.10.08-16:13
最后更新: 2018.11.14-10:42
版权声明: 本站文章均采用CC BY-NC-SA 4.0协议进行许可。转载请注明出处!