How to setup an SFTP server on CentOS

This tutorial explains how to setup and use an SFTP server on CentOS. Before I start, let me explain what actually SFTP represents and what it is used for. Currently, most people know that we can use normal FTP for transferring, downloading or uploading data from a server to client or client to server. But this protocol is getting hacked easily (if TLS is not used) by anonymous intruders as it the ports are wide open to anyone. Therefore, SFTP has been introduced to as another alternative to meet the main purpose to strengthen the security level.

SFTP stands for SSH File Transfer Protocol or Secure File Transfer Protocol. It uses a separate protocol packaged with SSH to provide a secure connection.

1. Preliminary Note

For this tutorial, I am using CentOS 7 in the 64bit version. The same steps will work on CentOS 6 as well. The tutorial result will show how a client can be provided with access to the SFTP server but unable to login to the server itself by SSH.

2. SFTP Installation

Unlike normal FTP, there’s no need to install additional packages in order to use SFTP. We just require the prebuild SSHd package that got already installed during installation on the server. Therefore, just check to confirm if you already have the required SSH package. Below are the steps:


rpm -qa|grep ssh

The output should be similar to this:

[root@localhost ~]# rpm -qa|grep sshlibssh2-1.4.3-10.el7_2.1.x86_64openssh-7.4p1-13.el7_4.x86_64openssh-server-7.4p1-13.el7_4.x86_64openssh-clients-7.4p1-13.el7_4.x86_64

That’s all, now we’ll go on how to make the SFTP configuration.

3. SFTP Configuration

Once all prerequisites of installation are done, we’ll step over to configuration phase. For best practice, we need to create a group and user so that we can manage all user that shall get SFTP access. But first, let’s create an additional folder called data. Below are the steps:

mkdir -p /data/sftpchmod 701 /data

Basically what I’m trying to do with the above step is to get a separate folder as main directory for the SFTP access. All user directories for the SFTP users will be subdirectories of this data folder.

Let’s create a group for the SFTP user, below are the steps:

groupadd sftpusers

Then create a user ‘howtoforge’ and assign it to the SFTPUSERS group. Below are the steps:

useradd -g sftpusers -d /upload -s /sbin/nologin mysftpuserpasswd mysftpuser
Changing password for user mysftpuser.New password:Retype new password:passwd: all authentication tokens updated successfully.

Below is the explanation of the above commands:

  1. I create a user and include the user into sftpusers group using -g command.
  2. I assign the main directory for the user to be in the /upload directory by setting the -d /upload command. This means that later the /upload folder will be under /data/mysftpuser/upload.
  3. I limit the access to the /sbin/nologin shell to ensure the user is only able to use the SFTP protocol, not SSH.
  4. I name the user “mysftpuser”.
  5. Set password for user “mysftpuser”.

Now let’s create the /upload folder under /data/mysftpuser, then assign appropriate ownership to the folder.

mkdir -p /data/mysftpuser/uploadchown -R root:sftpusers /data/mysftpuserchown -R mysftpuser:sftpusers /data/mysftpuser/upload

Once done, verify that the new folder under the directory /data exists and that we made the configuration correct.

[root@localhost ~]# ls -ld /data/drwx-----x. 5 root root 54 Mar 22 14:29 /data/
[root@localhost ~]# ls -ld /data/mysftpuserdrwxr-xr-x. 3 root sftpusers 20 Mar 22 14:29 /data/mysftpuser
[root@localhost ~]# ls -ld /data/mysftpuser/uploaddrwxr-xr-x. 2 mysftpuser sftpusers 6 Mar 22 14:29 /data/mysftpuser/upload
[root@localhost ~]# cat /etc/passwd|grep mysftpusermysftpuser:x:1001:1001::/upload:/sbin/nologin

Now configure the SSH protocol to create an SFTP process. This can be done by editing the configuration file under /etc/ssh/sshd_config. Below are the steps:

nano /etc/ssh/sshd_config

Add the following lines at the end of the file.

Match Group sftpusersChrootDirectory /data/%uForceCommand internal-sftp

Once done restart the SSH services, below are the steps:

service sshd status
Redirecting to /bin/systemctl status sshd.service? sshd.service - OpenSSH server daemonLoaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)Active: active (running) since Thu 2018-03-22 14:21:38 CET; 16min agoDocs: man:sshd(8)man:sshd_config(5)Main PID: 942 (sshd)CGroup: /system.slice/sshd.service??942 /usr/sbin/sshd -D
Mar 22 14:21:37 localhost.localdomain systemd[1]: Starting OpenSSH server daemon...Mar 22 14:21:38 localhost.localdomain sshd[942]: Server listening on port 22.Mar 22 14:21:38 localhost.localdomain sshd[942]: Server listening on :: port 22.Mar 22 14:21:38 localhost.localdomain systemd[1]: Started OpenSSH server daemon.Mar 22 14:21:49 localhost.localdomain sshd[1375]: Accepted password for root from port 59465 ssh2
service sshd restart
[root@localhost ~]# service sshd restartRedirecting to /bin/systemctl restart sshd.service

4. Testing SFTP

Now everything has been configured, so let’s make a test to ensure the setup meets our purpose.
I’ll access SFTP by using another server called TEST01. First, I’ll verify the Port of the SFTP server . To do that I’ll use the nmap function. If your client server didn’t have it you may download and install it with yum as shown below:

yum list nmap
Loaded plugins: fastestmirrorLoading mirror speeds from cached hostfile* base:* epel:* extras:* remi-php72:* remi-safe:* updates: ftp.rz.uni-frankfurt.deAvailable Packagesnmap.x86_64 2:6.40-7.el7
yum install nmap -y
Loaded plugins: fastestmirrorLoading mirror speeds from cached hostfile* base:* epel:* extras:* remi-php72:* remi-safe:* updates: ftp.rz.uni-frankfurt.deResolving Dependencies--> Running transaction check---> Package nmap.x86_64 2:6.40-7.el7 will be installed--> Processing Dependency: nmap-ncat = 2:6.40-7.el7 for package: 2:nmap-6.40-7.el7.x86_64--> Running transaction check---> Package nmap-ncat.x86_64 2:6.40-7.el7 will be installed--> Finished Dependency Resolution
Dependencies Resolved
=============================================================================================================================================================================================Package Arch Version Repository Size=============================================================================================================================================================================================Installing:nmap x86_64 2:6.40-7.el7 base 4.0 MInstalling for dependencies:nmap-ncat x86_64 2:6.40-7.el7 base 201 k
Transaction Summary=============================================================================================================================================================================================Install 1 Package (+1 Dependent package)
Total download size: 4.2 MInstalled size: 17 MDownloading packages:(1/2): nmap-ncat-6.40-7.el7.x86_64.rpm | 201 kB 00:00:01(2/2): nmap-6.40-7.el7.x86_64.rpm | 4.0 MB 00:00:14---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------Total 300 kB/s | 4.2 MB 00:00:14Running transaction checkRunning transaction testTransaction test succeededRunning transactionInstalling : 2:nmap-ncat-6.40-7.el7.x86_64 1/2Installing : 2:nmap-6.40-7.el7.x86_64 2/2Verifying : 2:nmap-ncat-6.40-7.el7.x86_64 1/2Verifying : 2:nmap-6.40-7.el7.x86_64 2/2
Installed:nmap.x86_64 2:6.40-7.el7
Dependency Installed:nmap-ncat.x86_64 2:6.40-7.el7
[root@localhost ~]# nmap -n
Starting Nmap 6.40 ( ) at 2018-03-22 14:51 CETNmap scan report for is up (0.000016s latency).Not shown: 997 closed portsPORT STATE SERVICE22/tcp open ssh
Nmap done: 1 IP address (1 host up) scanned in 0.12 seconds

You’ll notice that currently on our SFTP server, the only open port is SSH 22. Now, let’s try to access the SFTP server (IP: in my case) from TEST01 client. Below are the steps:

[root@TEST01 /]# sftp mysftpuser@'s password:Connected to> pwdRemote working directory: /uploadsftp>

Great! Now our SFTP server is accessible from outside. Notice that the default directory is /upload . This means that SFTP will only show the default path as /upload even though our previous configuration made in the SFTP server directory is /data/mysftpuser/upload.
Now let’s try to get a file from the SFTP server directory into our testing client. First, let’s create a test file under /data/mysftpuser/upload. Below are the steps:Advertisements

cd /data/mysftpuser/uploadtouch testing_file.txt

Then go back to our testing site TEST01 and see if we able to get and download the created file.

[root@TEST01 /]# sftp mysftpuser@'s password:Connected to> pwdRemote working directory: /uploadsftp> lstesting_file.txtsftp> get testing_file.txtFetching /upload/testing_file.txt to testing_file.txtsftp> quit

Excellent! Our SFTP test has been successful, let’s try to access SSH using the user mysftpuser. As previously, we’ve set configuration as /sbin/nologin, therefore the user won’t be able to use SSH services:

[root@TEST01 ~]# ssh mysftpuser@'s password:This service allows sftp connections only.Connection to closed.

Nice! Now we have a secured SFTP server up and running.

How to set DNS in CentOS/RHEL 7 & prevent NetworkManager from overwriting /etc/resolv.conf?

This guide shows you how to set custom DNS entries for CentOS 7 / RedHat 7 and ensure that the settings are persistent even after a reboot.

What you need

  • A CentOS 7 or a Red Hat Enterprise Linux (RHEL) 7 server
  • A couple of minutes


In CentOS and Red Hat Enterprise Linux (RHEL) 7, any custom DNS entries are stored in the file /etc/resolv.conf. However, if we simply go ahead and add our nameservers to this file, we’ll notice that after a reboot or a restart of the network.service, the file is overwritten by NetworkManager.

In this guide, we will first configure NetworkManager to not overwrite this file. Then, we will go ahead and actually add our custom nameservers to /etc/resolv.conf.

Step 1

The NetworkManager configuration is located here: /etc/NetworkManager/NetworkManager.conf Open this file using vim or your favorite text editor.

Search for the [main] section in this file. It should look something like this:


Add dns=none just after the [main] tag like this:


Go ahead and save the file.

Step 2

Let’s restart the NetworkManager.service service so that it picks up the changes we made to the configuration.

sudo systemctl restart NetworkManager.service

Note that the service name NetworkManager.service is case-sensitive.

Step 3

Now, let’s add our nameservers to /etc/resolv.conf

Open this file in you favorite text editor and specify the name servers as follows:

# Generated by NetworkManager

That’s it! You’re done. The nameservers added to /etc/resolv.conf will now persist even after a reboot. NetworkManager will not longer overwrite this file.

Centos curl ssl 替换 NSS 为 OpenSSL

系统版本是 Centos 6/7 64位。


yum groupinstall Development tools


1.下载 OpenSSL:


2.解压 OpenSSL:

tar -xzvf openssl-1.0.2l.tar.gz

3.进入 OpenSSL目录:

cd openssl-1.0.2l

4.配置并编译 OpenSSL:

./config –shared
make && make install


1.下载 curl 库:


2.解压 curl 库:

tar -xzvf curl-7.55.1.tar.gz

3.进入 curl 目录:

cd curl-7.55.1


export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/ssl/lib

5.配置并编译 curl:

./configure –prefix=/usr/local/curl/ –without-nss –with-ssl=/usr/local/ssl/
make && make install

6.备份默认的 curl 二进制文件

mv /usr/bin/curl /usr/bin/curl.bak

7.做一个新的 curl 软链

ln -s /usr/local/curl/bin/curl /usr/bin/curl

总体的替换到此就完成,可以执行 curl –version 来进行确认。下边是我执行的结果:

curl 7.55.1 (x86_64-pc-linux-gnu) libcurl/7.55.1 OpenSSL/1.0.2l
Release-Date: 2017-08-14
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IPv6 Largefile NTLM NTLM_WB SSL TLS-SRP UnixSockets HTTPS-proxy

CentOs 6 64 Bit系统操作实例:

# curl -V

curl 7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/ Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2

Protocols: tftp ftp telnet dict ldap ldaps http file https ftps scp sftp

Features: GSS-Negotiate IDN IPv6 Largefile NTLM SSL libz

 # curl

 # tar zxvf curl-7.69.1.tar.gz

 #  cd curl-7.69.1

 #  ./configure –prefix=/usr/local/curl/ –without-nss –with-ssl

 #  make && make install

 # /usr/local/curl/bin/curl -V

curl 7.69.1 (x86_64-pc-linux-gnu) libcurl/7.69.1 OpenSSL/1.0.1e-fips zlib/1.2.3

Release-Date: 2020-03-11

Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp

Features: AsynchDNS HTTPS-proxy IPv6 Largefile libz NTLM NTLM_WB SSL UnixSockets

# ldd /usr/local/curl/bin/curl =>  (0x00007ffd0c5bf000) => /usr/local/curl/lib/ (0x00007f6513ab3000) => /usr/lib64/ (0x00007f6513837000) => /usr/lib64/ (0x00007f6513454000) => /lib64/ (0x00007f651323e000) => /lib64/ (0x00007f6513035000) => /lib64/ (0x00007f6512ca1000) => /lib64/ (0x00007f6512a5d000) => /lib64/ (0x00007f6512776000) => /lib64/ (0x00007f6512572000) => /lib64/ (0x00007f6512346000) => /lib64/ (0x00007f6512141000) => /lib64/ (0x00007f6511f24000)

        /lib64/ (0x0000564ebdb90000) => /lib64/ (0x00007f6511d19000) => /lib64/ (0x00007f6511b15000) => /lib64/ (0x00007f65118fb000) => /lib64/ (0x00007f65116db000)


# curl -V

curl 7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/ Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2

Protocols: tftp ftp telnet dict ldap ldaps http file https ftps scp sftp

Features: GSS-Negotiate IDN IPv6 Largefile NTLM SSL libz

# ldd /usr/bin/curl           =>  (0x00007ffde3fec000) => /usr/lib64/ (0x00007fcbc9064000) => /lib64/ (0x00007fcbc8e32000) => /lib64/ (0x00007fcbc8be1000) => /lib64/ (0x00007fcbc89d9000) => /lib64/ (0x00007fcbc8795000) => /lib64/ (0x00007fcbc84ae000) => /lib64/ (0x00007fcbc8282000) => /lib64/ (0x00007fcbc807e000) => /usr/lib64/ (0x00007fcbc7e3e000) => /usr/lib64/ (0x00007fcbc7c12000) => /usr/lib64/ (0x00007fcbc78d3000) => /usr/lib64/ (0x00007fcbc76a6000) => /lib64/ (0x00007fcbc74a2000) => /lib64/ (0x00007fcbc729d000) => /lib64/ (0x00007fcbc705e000) => /lib64/ (0x00007fcbc6e41000) => /lib64/ (0x00007fcbc6c3d000) => /usr/lib64/ (0x00007fcbc6a14000) => /lib64/ (0x00007fcbc67fe000) => /lib64/ (0x00007fcbc646a000) => /lib64/ (0x00007fcbc625a000) => /lib64/ (0x00007fcbc6040000) => /usr/lib64/ (0x00007fcbc5e26000)

        /lib64/ (0x000055a80dede000) => /lib64/ (0x00007fcbc5c1a000) => /lib64/ (0x00007fcbc5a17000) => /usr/lib64/ (0x00007fcbc57aa000) => /usr/lib64/ (0x00007fcbc53c7000) => /lib64/ (0x00007fcbc5190000) => /lib64/ (0x00007fcbc4f70000) => /lib64/ (0x00007fcbc4cf7000)

# ldd /usr/bin/curl =>  (0x00007ffd715e1000) => /usr/lib64/ (0x00007efcd84af000) => /lib64/ (0x00007efcd827d000) => /lib64/ (0x00007efcd802c000) => /lib64/ (0x00007efcd7e24000) => /lib64/ (0x00007efcd7be0000) => /lib64/ (0x00007efcd78f9000) => /lib64/ (0x00007efcd76cd000) => /lib64/ (0x00007efcd74c9000) => /usr/lib64/ (0x00007efcd7289000) => /usr/lib64/ (0x00007efcd705d000) => /usr/lib64/ (0x00007efcd6d1e000) => /usr/lib64/ (0x00007efcd6af1000) => /lib64/ (0x00007efcd68ed000) => /lib64/ (0x00007efcd66e8000) => /lib64/ (0x00007efcd64a9000) => /lib64/ (0x00007efcd628c000) => /lib64/ (0x00007efcd6088000) => /usr/lib64/ (0x00007efcd5e5f000) => /lib64/ (0x00007efcd5c49000) => /lib64/ (0x00007efcd58b5000) => /lib64/ (0x00007efcd56a5000) => /lib64/ (0x00007efcd548b000) => /usr/lib64/ (0x00007efcd5271000)

        /lib64/ (0x00005572fd9ce000) => /lib64/ (0x00007efcd5065000) => /lib64/ (0x00007efcd4e62000) => /usr/lib64/ (0x00007efcd4bf5000) => /usr/lib64/ (0x00007efcd4812000) => /lib64/ (0x00007efcd45db000) => /lib64/ (0x00007efcd43bb000) => /lib64/ (0x00007efcd4142000)

# vi .bash_profile

# .bash_profile

# Get the aliases and functions

if [ -f ~/.bashrc ]; then

        . ~/.bashrc


# User specific environment and startup programs




# /usr/bin/curl -V

curl 7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.69.1 OpenSSL/1.0.1e-fips zlib/1.2.3

Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp

Features: AsynchDNS IPv6 Largefile NTLM SSL libz

# ldd /usr/bin/curl =>  (0x00007fff7c777000) => /usr/local/curl/lib/ (0x00007fb5ed9b4000) => /lib64/ (0x00007fb5ed772000) => /lib64/ (0x00007fb5ed522000) => /lib64/ (0x00007fb5ed31a000) => /lib64/ (0x00007fb5ed0d5000) => /lib64/ (0x00007fb5ecdef000) => /lib64/ (0x00007fb5ecbc3000) => /lib64/ (0x00007fb5ec9be000) => /usr/lib64/ (0x00007fb5ec77f000) => /usr/lib64/ (0x00007fb5ec553000) => /usr/lib64/ (0x00007fb5ec213000) => /usr/lib64/ (0x00007fb5ebfe7000) => /lib64/ (0x00007fb5ebde3000) => /lib64/ (0x00007fb5ebbdd000) => /lib64/ (0x00007fb5eb99f000) => /lib64/ (0x00007fb5eb782000) => /lib64/ (0x00007fb5eb57d000) => /usr/lib64/ (0x00007fb5eb355000) => /lib64/ (0x00007fb5eb13f000) => /lib64/ (0x00007fb5eadaa000) => /usr/lib64/ (0x00007fb5eab3e000) => /usr/lib64/ (0x00007fb5ea75b000) => /lib64/ (0x00007fb5ea54b000) => /lib64/ (0x00007fb5ea331000) => /usr/lib64/ (0x00007fb5ea117000)

        /lib64/ (0x0000564abf25b000) => /lib64/ (0x00007fb5e9f0b000) => /lib64/ (0x00007fb5e9d08000) => /lib64/ (0x00007fb5e9ad0000) => /lib64/ (0x00007fb5e98b1000) => /lib64/ (0x00007fb5e9637000)

Renew/Extend Puppet CA/puppetmasterd certs

Puppet CA/puppetmasterd cert renewal

While we’re still converting our puppet controlled infra to Ansible, we still have some nodes “controlled” by puppet, as converting some roles isn’t something that can be done in just one or two days. Add to that other items in your backlog that all have priority set to #1 and then time is flying, until you realize this for your existing legacy puppet environment (assuming false FQDN here, but you’ll get the idea):

Warning: Certificate 'Puppet CA:' will expire on 2019-05-06T12:12:56UTC
Warning: Certificate '' will expire on 2019-05-06T12:12:56UTC

So, as long as your PKI setup for puppet is still valid, you can act in advance, resign/extend CA and puppetmasterd and distribute newer CA certs to agents, and go forward with other items in your backlog, while still converting from puppet to Ansible (at least for us)


Before anything else, (in case you don’t backup this, but you should), let’s take a backup on the Puppet CA (in our case, it’s a Foreman driven puppetmasterd, so foreman host is where all this will happen, YMMV)

tar cvzf /root/puppet-ssl-backup.tar.gz /var/lib/puppet/ssl/

CA itself

We first need to regenerate the CSR for the CA cert, and sign it again Ideally we confirm that the ca_key.pem and the existing ca_crt.pem “matches” through modulus (should be equals)

cd /var/lib/puppet/ssl/ca
( openssl rsa -noout -modulus -in ca_key.pem  2> /dev/null | openssl md5 ; openssl x509 -noout -modulus -in ca_crt.pem  2> /dev/null | openssl md5 ) 

(stdin)= cbc4d35f58b28ad7c4dca17bd4408403
(stdin)= cbc4d35f58b28ad7c4dca17bd4408403

As it’s the case, we can now Regenerate from that private key and existing crt a CSR

openssl x509 -x509toreq -in ca_crt.pem -signkey ca_key.pem -out ca_csr.pem
Getting request Private Key
Generating certificate request

Now that we have the CSR for CA, we need to sign it again, but we have to add extensions

cat > extension.cnf << EOF
basicConstraints = critical,CA:TRUE
nsComment = "Puppet Ruby/OpenSSL Internal Certificate"
keyUsage = critical,keyCertSign,cRLSign
subjectKeyIdentifier = hash

And now archive old CA crt and sign (new) extended one

cp ca_crt.pem ca_crt.pem.old
openssl x509 -req -days 3650 -in ca_csr.pem -signkey ca_key.pem -out ca_crt.pem -extfile extension.cnf -extensions CA_extensions
Signature ok
subject=/CN=Puppet CA:
Getting Private key

openssl x509 -in ca_crt.pem -noout -text|grep -A 3 Validity
            Not Before: Apr 29 08:25:49 2019 GMT
            Not After : Apr 26 08:25:49 2029 GMT

Puppetmasterd server

We have also to regen the CSR from the existing cert (assuming our fqdn for our cert is correctly also the currently set hostname)

cd /var/lib/puppet/ssl
openssl x509 -x509toreq -in certs/$(hostname).pem -signkey private_keys/$(hostname).pem -out certificate_requests/$(hostname)_csr.pem
Getting request Private Key
Generating certificate request

Now that we have CSR, we can sign with new CA

cp certs/$(hostname).pem certs/$(hostname).pem.old #Backing up
openssl x509 -req -days 3650 -in certificate_requests/$(hostname)_csr.pem -CA ca/ca_crt.pem \
  -CAkey ca/ca_key.pem -CAserial ca/serial -out certs/$(hostname).pem
Signature ok  

Validating that puppetmasted key and new certs are matching (so crt and private keys are ok)

( openssl rsa -noout -modulus -in private_keys/$(hostname).pem  2> /dev/null | openssl md5 ; openssl x509 -noout -modulus -in certs/$(hostname).pem 2> /dev/null | openssl md5 )

(stdin)= 0ab385eb2c6e9e65a4ed929a2dd0dbe5
(stdin)= 0ab385eb2c6e9e65a4ed929a2dd0dbe5

It seems all good, so let’s restart puppetmasterd/httpd (foremand launches puppetmasterd for us)

systemctl restart puppet

Puppet agents

From this point, puppet agents will not complain about the puppetmasterd cert, but still about the fact that CA itself will expire soon :

Warning: Certificate 'Puppet CA:' will expire on 2019-05-06T12:12:56GMT

But as we have now the new ca_crt.pem at the puppetmasterd/foreman side, we can just distribute it on clients (through puppet or ansible or whatever) and then it will continue to work

cd /var/lib/puppet/ssl/certs
mv ca.pem ca.pem.old

And now distribute the new ca_crt.pem as ca.pem here

puppet snippet for this (in our puppet::agent class)

 file { '/var/lib/puppet/ssl/certs/ca.pem': 
   source => 'puppet:///puppet/ca_crt.pem', 
   owner => 'puppet', 
   group => 'puppet', 
   require => Package['puppet'],

Next time you’ll “puppet agent -t” or that puppet will contact puppetmasterd, it will apply the new cert on and on next call, no warning, issue anymore

Info: Computing checksum on file /var/lib/puppet/ssl/certs/ca.pem
Info: /Stage[main]/Puppet::Agent/File[/var/lib/puppet/ssl/certs/ca.pem]: Filebucketed /var/lib/puppet/ssl/certs/ca.pem to puppet with sum c63b1cc5a39489f5da7d272f00ec09fa
Notice: /Stage[main]/Puppet::Agent/File[/var/lib/puppet/ssl/certs/ca.pem]/content: content changed '{md5}c63b1cc5a39489f5da7d272f00ec09fa' to '{md5}e3d2e55edbe1ad45570eef3c9ade051f'

Hope it helps

How to allocate a large memory space for Informix shared memory segments



How to allocate a large memory space for Informix shared memory segments on Red Hat Linux 3 (RHEL3).

Resolving The Problem


You are using IBM® Informix® Dynamic server (IDS) on on Red Hat Linux 3. When you try to allocate more that 1.8 GB (Gigabytes) of shared memory, the following error message appears in the message log file.

13:52:26 shmat: [ENOMEM][12]: out of available data space, check system memory parameters (e.g. MAXMEM).


The following products and operating systems are affected:

Product NameProduct Version(s)Hardware VendorOperating System
IBM® Informix® Dynamic Server™10.00.UC3 AllRed Hat Linux 3


The limitation of 1.8 GB is due to the placement of the IDS Shared Memory base address which by default is 0x44000000.

Important: This is only one possible cause of the problem. If this document does not provide you with a solution to your problem, you should search for other documents that refer to this topic.


The layout of shared memory can be seen by running the following command (pid is the process id of the main CPU VP).

$ cat /proc/”pid”/maps

089f8000-08b7c000 rw-p 009b0000 08:02 655537     /usr3/products/10.0/bin/oninit
08b7c000-08bfe000 rw-p 00000000 00:00 0
0a01b000-0a03c000 rw-p 00000000 00:00 0
<Shared memory starts here>
44000000-45419000 rw-s 00000000 00:04 8519685    /SYSV52c44801 (deleted)
45419000-49419000 rw-s 00000000 00:04 8552455    /SYSV52c44802 (deleted)
49419000-494a0000 rw-s 00000000 00:04 8585224    /SYSV52c44803 (deleted)
<Shared memory ends here>
b75ea000-b75ed000 rw-p 00001000 00:00 0
bffbc000-c0000000 rwxp fffc0000 00:00 0

With the default SHMBASE, you can allocate a total shared memory allocation (RESIDENT + MESSAGE + VIRTUAL) of approximately 1.845GB

0xb75ea000 – 0x44000000 = 0x735EA000
= 1935581184
= 1,845 GB (approximately)

This can be seen from output of the onstat command:

$ onstat -g seg

IBM Informix Dynamic Server Version 10.00.UC3     — On-Line — Up 00:00:16 — 1821120 Kbytes

Segment Summary:
id       key        addr     size       ovhd     class blkused  blkfree
8617989  1388595201 44000000 21073920   215476   R     5141     4
8650759  1388595202 45419000 1843200000 56904    V     3490     446510  
8683528  1388595203 b31e9000 552960     672      M     135      0
Total:   –          –        1864826880 –        –     8766     446514

   (* segment locked in memory)

However, if the Shared Memory Base address is lowered down from 0x44000000 to 0x0b000000, you can allocate a total memory allocation of almost 2.8GB.


in your onconfig configuration file and increase shared memory parameters to utilise more memory.

$ onstat -g seg

IBM Informix Dynamic Server Version 10.00.UC3     — On-Line — Up 00:00:21 — 2721120 Kbytes

Segment Summary:
id       key        addr     size       ovhd     class blkused  blkfree
8880133  1388595201 b000000  21073920   215476   R     5141     4
8912903  1388595202 c419000  2764800000 85024    V     3486     671514
8978441  1388595204 b10d1000 552960     672      M     135      0
Total:   –          –        2786426880 –        –     8762     671518

   (* segment locked in memory)

$ cat /proc/731/maps
089f8000-08b7c000 rw-p 009b0000 08:02 655537     /usr3/products/10.0/bin/oninit
08b7c000-08bfe000 rw-p 00000000 00:00 0
08f32000-08f53000 rw-p 00000000 00:00 0
0b000000-0c419000 rw-s 00000000 00:04 10813445   /SYSV52c44801 (deleted)
0c419000-5ea75000 rw-s 00000000 00:04 10846215   /SYSV52c44802 (deleted)
5ea75000-b10d1000 rw-s 00000000 00:04 10878984   /SYSV52c44803 (deleted)
b10d1000-b1158000 rw-s 00000000 00:04 10911753   /SYSV52c44804 (deleted)
b75ea000-b75ed000 rw-p 00000000 00:00 0
bffbe000-c0000000 rwxp fffc0000 00:00 0

Note: The operating system has split the virtual memory segment into 2 equal sizes. This is because the virtual segment is greater than 2 GB and the operating system segment size has been limited to 2 GB:

$ ipcs -ma

—— Shared Memory Segments ——–
key        shmid      owner      perms      bytes      nattch     status
0x52c44801 10813445   root      660        21073920   14
0x52c44802 10846215   root      660        1382400000 14
0x52c44803 10878984   root      660        1382400000 14
0x52c44804 10911753   root      666        552960     14



IBM Informix Dynamic Server Version 11.70.UC7(CentOS 6.4 32Bit)在进行0级恢复时出现过,具体参数变更如下解决:
SHMBASE 0x44000000 -> 0xB000000L


The Mega Guide To Harden and Secure CentOS 7

This tutorial only covers general security tips for CentOS 7 which can be used to harden the system. The checklist tips are intended to be used mostly on various types of bare-metal servers or on machines (physical or virtual) that provides network services.

Security and Hardening of CentOS 7

Security and Hardening of CentOS 7

However, some of tips can be successfully applied on general purpose machines too, such as Desktops, Laptops and card-sized single-board computers (Raspberry Pi).


  1. CentOS 7 Minimal Installation

1. Physical Protection

Lock down your server rooms access, use racks locking and video surveillance. Take into consideration that any physical access to server rooms can expose your machine to serious security issues.

BIOS passwords can be changed by resetting jumpers on the motherboard or by disconnecting the CMOS battery. Also, an intruder can steal the hard disks or directly attach new hard disks to the motherboard interfaces (SATA, SCSI etc), boot up with a Linux live distro and clone or copy data without leaving any software trace.

2. Reduce Spying Impact

In case of highly sensitive data you should probably use advanced physical protection such as placing and locking the server into a Faraday Cage or use a military TEMPEST solution in order to minimize the impact of spying the system via radio or electrical leaking emanations.

3. Secure BIOS/UEFI

Start the process of harden your machine by securing BIOS/UEFI settings, especially set a BIOS/UEFI password and disable boot media devices (CD, DVD, disable USB support) in order to prevent an unauthorized users from modifying the system BIOS settings or altering the boot device priority and booting the machine from an alternate medium.

In order to apply this type of changes to your machine you need to consult the motherboard manufacturer manual for specific instructions.

4. Secure Boot Loader

Set a GRUB password in order to prevent malicious users to tamper with kernel boot sequence or runlevels, edit kernel parameters or start the system into single user mode in order to harm your system and reset root password to gain privileged control.

5. Use Separate Disk Partitions

When installing CentOS on systems intended as production servers use dedicated partitions or dedicated hard disks for the following parts of the system:


6. Use LVM and RAID for Redundancy and File System Growth

The /var partition is the place where log messages are written to disk. This part of the system can exponential grow in size on heavily traffic servers which expose network services such as web servers or file servers.

Thus, use a large partition for /var or consider on setting up this partition using logical volumes (LVM) or combine several physical disks into one larger virtual RAID 0 device to sustain large amounts of data. For data redundancy consider on using LVM layout on top of RAID 1 level.

For setting up LVM or RAID on the disks, follow our useful guides:

  1. Setup Disk Storage with LVM in Linux
  2. Create LVM Disks Using vgcreate, lvcreate and lvextend
  3. Combine Several Disks into One Large Virtual Storage
  4. Create RAID 1 Using Two Disks in Linux

7. Modify fstab Options to Secure Data Partitions

Separate partitions intended for storing data and prevent the execution of programs, device files or setuid bit on these type of partitions by adding the following options to fstab file as illustrated on the below excerpt:

/dev/sda5 	 /nas          ext4    defaults,nosuid,nodev,noexec 1 2

To prevent privilege-escalation and arbitrary script execution create a separate partition for /tmp and mount it as nosuidnodev and noexec.

/dev/sda6  	/tmp         ext4    defaults,nosuid,nodev,noexec 0 0

8. Encrypt the Hard Disks at block level with LUKS

In order to protect sensitive data snooping in case of physical access to machine hard drives. I suggest you to learn how to encrypt disk by reading our article Linux Hard Disk Data Encryption with LUKS.

9. Use PGP and Public-Key Cryptography

In order to encrypt disks, use PGP and Public-Key Cryptography or openssl command to encrypt and decrypt sensitive files with a password as shown in this article Configure Encrypted Linux System Storage.

10. Install Only the Minimum Amount of Packages Required

Avoid installing unimportant or unnecessary programs, applications or services to avoid package vulnerabilities. This can decrease the risk that the compromise of a piece of software may lead to compromise other applications, parts of the system or even file systems, finally resulting in data corruption or data loss.

11. Update the system frequently

Update the system regularly. Keep Linux kernel in sync with the latest security patches and all the installed software up-to-date with the latest versions by issuing the below command:

# yum update

12. Disable Ctrl+Alt+Del

In order to prevent users to reboot the server once they have physical access to keyboard or via a Remote Console Application or a virtualized console (KVM, Virtualizing software interface) you should disable Ctrl+Alt+Del key sequence by executing the below command.

# systemctl mask 

13. Remove Unnecessary Software Packages

Install minimal software required for your machine. Never install extra programs or services. Install packages only from trusted or official repositories. Use minimal installation of the system in case the machine is destined to run its entire live as a server.

Verify installed packages using one of the following commands:

# rpm -qa

Make a local list of all installed packages.

# yum list installed >> installed.txt

Consult the list for useless software and delete a package by issuing the below command:

# yum remove package_name

Read AlsoDisable and Remove Unwanted Packages on Minimal Installation of CentOS 7.

14. Restart systemd services after daemon updates

Use the below command example to restart a systemd service in order to apply new updates.

# systemctl restart httpd.service

15. Remove Unneeded Services

Identify the services that are listening on specific ports using the following command.

# ss -tulpn

To list all installed services with their output status issue the below command:

# systemctl list-units -t service

For instance, CentOS 7 default minimal installation comes with Postfix daemon installed by default which runs by the name of master under port 25. Remove Postfix network service in case your machine will not be used as a mail server.

# yum remove postfix

Read AlsoStop and Disable Unwanted Services in CentOS 7.

16. Encrypt Transmitted Data

Do not use unsecure protocols for remote access or file transfer such as TelnetFTP or other plain text high protocols such as SMTP, HTTP, NFS or SMB which, by default, does not encrypt the authentication sessions or sent data.

Use only sftpscp for file transfers and SSH or VNC over SSH tunnels for remote console connections or GUI access.

In order to tunnel a VNC console via SSH use the below example which forwards the VNC port 5901 from the remote machine to your local machine:

# ssh -L 5902:localhost:5901 remote_machine

On local machine run the below command in order to virtual connect to the remote endpoint.

# vncviewer localhost:5902

17. Network Port Scanning

Conduct external port checks using the nmap tool from a remote system over the LAN. This type of scanning can be used to verify network vulnerabilities or test the firewall rules.

# nmap -sT -O

Read AlsoLearn How to Use Nmap with these 29 Examples.

18. Packet-filtering Firewall

Use firewalld utility to protect the system ports, open or close specific services ports, especially well-known ports (<1024).

Install, start, enable and list the firewall rules by issuing the below commands:

# yum install firewalld
# systemctl start firewalld.service
# systemctl enable firewalld.service
# firewall-cmd --list-all

19. Inspect Protocol Packets with tcpdump

Use tcpdump utility in order to sniff network packets locally and inspect their content for suspicious traffic (source-destination ports, tcp/ip protocols, layer two traffic, unusual ARP requests).

For a better analysis of the tcpdump captured file use a more advanced program such as Wireshark.

# tcpdump -i eno16777736 -w tcpdump.pcap

Read Also12 tcpdump Command Examples and Analyze Network Using Wireshark Tool.

20. Prevent DNS Attacks

Inspect the contents of your resolver, typically /etc/resolv.conf file, which defines the IP address of the DNS servers it should use to query for domain names, in order to avoid man-in-the-middle attacks, unnecessary traffic for root DNS servers, spoof or create a DOS attack.

This is just the first part. On the next part we’ll discuss other security tips for CentOS 7.

Continuing the previous tutorial on how to secure CentOS 7, in this article we’ll discuss other security tips that will be presented on the below checklist.

Hardening and Securing of CentOS 7 Server

Hardening and Securing of CentOS 7 Server


  1. The Mega Guide To Harden and Secure CentOS 7 – Part 1

21. Disable Useless SUID and SGID Commands

If the setuid and setgid bits are set on binary programs, these commands can run tasks with other user or group rights, such as root privileges which can expose seriously security issues.

Often, buffer overrun attacks can exploit such executables binaries to run unauthorized code with the rights of a root power user.

# find /  -path /proc -prune -o -type f \( -perm -4000 -o -perm -2000 \) -exec ls -l {} \;

To unset the setuid bit execute the below command:

# chmod u-s /path/to/binary_file

To unset the setgid bit run the below command:

# chmod g-s /path/to/binary_file

22. Check for Unowned Files and Directories

Files or directories not owned by a valid account must be deleted or assigned with permissions from a user and group.

Issue the below command to list files or directories with no user and group.

# find / -nouser -o -nogroup -exec ls -l {} \;

23. List World-Writeable Files

Keeping word-writable file on the system can be dangerous due to the fact that anyone can modify them. Execute the below command in order to display word-writeable files, except Symlinks, which are always world-writeable.

# find / -path /proc -prune -o -perm -2 ! -type l –ls

24. Create Strong Passwords

Create a password of minimum of eight characters. The password must contain digits, special characters and uppercase letters. Use pwmake to generate a password of 128 bits from /dev/urandom file.

# pwmake 128

25. Apply Strong Password Policy

Force the system to use strong passwords by adding the below line in /etc/pam.d/passwd file.

password required retry=3

Adding the above line, the password entered cannot contain more than 3 characters in a monotonic sequence, such as abcd, and more than 3 identical consecutive characters, such as 1111.

To force users to use a password with a minimum length of 8 characters, including all classes of characters, strength-check for character sequences and consecutive characters add the following lines to the /etc/security/pwquality.conf file.

minlen = 8
minclass = 4
maxsequence = 3
maxrepeat = 3

Sharing is Caring…

26. Use Password Aging

The chage command can be used for user password aging. To set a user’s password to expire in 45 days, use the following command:

# chage -M 45 username

To disable password expiration time use the command:

# chage -M -1 username

Force immediate password expiration (user must change password on next login) by running the following command:

# chage -d 0 username

27. Lock Accounts

User accounts can be locked by executing the passwd or usermod command:

# passwd -l username
# usermod -L username

To unlock accounts use the -u option for passwd command and -U option for usermod.

28. Prevent Accounts Shell Access

To prevent a system account (ordinary account or service account) to gain access to bash shell, change root shell to /usr/sbin/nologin or /bin/false in the /etc/passwd file by issuing the command below:

# usermod -s /bin/false username

To change the shell when creating a new user issue the following command:

# useradd -s /usr/sbin/nologin username

Read AlsoLearn 15 Examples of “useradd” Command in Linux

29. Lock Virtual User Console with vlock

vlock is a program used for locking one multiple sessions on Linux console. Install the program and start locking your terminal session by running the below commands:

# yum install vlock
# vlock

30. Use a Centralized System to Manage Accounts and Authentication

Using a centralized authentication system can greatly simplify account management and control. Services that can offer this type of account management are: IPA Server, LDAP, Kerberos, Microsoft Active Directory, Nis, Samba ADS or Winbind.

Some of these services are by default highly secured with cryptographic protocols and symmetric-key cryptography, such as Kerberos.

Read AlsoSetup NFS Server with Kerberos-based User Authentication in Linux

31. Force Read-Only Mounting of USB Media

Using blockdev utility you can force all removable media to be mounted as read-only. For instance, create a new udev configuration file named 80-readonly-usb.rules in the /etc/udev/rules.d/ directory with the following content:

SUBSYSTEM=="block",ATTRS{removable}=="1",RUN{program}="/sbin/blockdev --setro %N"

Then, apply the rule with the below command:

# udevadm control -reload

32. Disabling Root Access via TTY

To prevent the root account from performing system log-in via all console devices (tty), erase the contents of securetty file by typing the following command terminal prompt as root.

# cp /etc/securetty /etc/securetty.bak
# cat /dev/null > /etc/securetty

Remember that this rule does not apply to SSH login sessions
To prevent root login via SSH edit the file /etc/ssh/sshd_config and add the below line:

PermitRootLogin no

Read AlsoEnable or Disable SSH Root Login and Limit SSH Access
5 Best Practices to Secure and Protect SSH Server

Sharing is Caring…

33. Use POSIX ACLs to Expand System Permissions

Access Control Lists can define access rights for more than just a single user or group and can specify rights for programs, processes, files, and directories. If you set ACL on a directory, its descendants will inherit the same rights automatically.

For example,

# setfacl -m u:user:rw file
# getfacl file

Read AlsoSetup ACL and Disk Quotas for Users/Groups in Linux

34. Setup SELinux in Enforce Mode

The SELinux enhancement to the Linux kernel implements the Mandatory Access Control (MAC) policy, allowing users to define a security policy that provides granular permissions for all users, programs, processes, files, and devices.

The kernel’s access control decisions are based on all the security relevant context and not on the authenticated user identity.

To get Selinux status and enforce policy run the below commands:

# getenforce
# setenforce 1
# sestatus

Read AlsoSetup Mandatory Access Control Policy with SELinux

35. Install SELinux Additional Utilities

Install policycoreutils-python package which provides additional Python utilities for operating SELinuxaudit2allowaudit2whychcat, and semanage.

To display all boolean values together with a short description, use the following command:

# semanage boolean -l

For instance, to display and set the value of httpd_enable_ftp_server, run the below command:

# getsebool httpd_enable_ftp_server

To make the value of a boolean persist across reboots, specify the -P option to setsebool, as illustrated on the following example:

# setsebool -P httpd_enable_ftp_server on

36. Use Centralized Log Server

Configure rsyslog daemon to send sensitive utilities log messages to a centralized log server. Also, monitor log files with the help of logwatch utility.

Sending log messages to a remote server assures that once the system has been compromised, the malicious users cannot completely hide their activity, always leaving traces on remote log files.

Read Also4 Best Linux Log Monitoring and Management Tools

37. Enable Process Accounting

Enable process accounting by installing psacct utility.

Read AlsoMonitor Linux User Activity with psacct or acct Tools

Use lastcomm command to displays information about previously executed commands as recorded in the system accounting file and sa to summarize information about previously executed commands as recorded in the system accounting file.

38. Hardening /etc/sysctl.conf

Use the following kernel parameters rules to protect the system:

Disabling Source Routing


Disable IPv4 forwarding


Disable IPv6

net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

Disable the acceptance and sending of ICMP redirected packets unless specifically required.


Disable Reverse Path Forwarding


Ignore all ICMP echo requests (set to 1 to enable)

net.ipv4.icmp_echo_ignore_all = 0

Read AlsoSet Kernel Runtime Parameters in a Persistent and Non-Persistent Way

39. Use VPN Services to Access your Premises over Unprotected Public Networks

Always use VPN services for carriers to remotely access LAN premises over Internet. Such type of services can be configured using a free open source solution, such as OpenVPN, or using a proprietary solution, such as Cisco VPN (install vpnc command-line utility provided by Epel Repositories).

Read AlsoInstall OpenVPN Server with Windows Clients in CentOS 7

40. Perform External System Scan

Evaluate your system security for vulnerabilities by scanning the system from remote points over your LAN using specific tools such as:

  1. Nmap – network scanner 29 Examples of Nmap Command
  2. Nessus – security scanner
  3. OpenVAS – used to scan for vulnerabilities and for comprehensive vulnerability management.
  4. Nikto – an excellent common gateway interface (CGI) script scanner Scan Web Vulnerability in Linux

41. Protect System Internally

Use internal system protection against viruses, rootkits, malware and, as a good practice, install intrusion detection systems that can detect unauthorized activity (DDOS attacks, port scans), such as:

  1. AIDE – Advanced Intrusion Detection Environment –
  2. ClamAV – Antivirus Scanner
  3. Rkhunter – Rootkit Dcanner
  4. Lynis – Security Auditing and Scanning Tool for Linux
  5. Tripwire – Security and Data Integrity
  6. Fail2Ban – Intrusion Network Prevention
  7. OSSEC – (HIDS) Host-based Intrusion Detection System
  8. Mod_Security – Protect Brute Force or DDoS Attacks

42. Modify User Environment Variables

Append date and time format to store commands execution by issuing the below command:

# echo 'HISTTIMEFORMAT="%d/%m/%y  %T  "' >> .bashrc'

Force to instantly record HISTFILE every time a command is typed (instead of logout):

# echo ‘PROMPT_COMMAND="history -a"’ >> .bashrc

Limit timeout login session. Automatically tear-down the shell when no activity is performed during idle time period. Very useful to automatically disconnect SSH sessions.

# echo ‘TMOUT=120’ >> .bashrc

Apply all the rules by executing:

# source .bashrc

Read Also Set User Environment Variables in Linux

43. Backup Data

Use backup utilities, such as tarcatrsyncscpLVM snapshots, etc in order to store a copy of your system, preferably offsite, in case of a system failure.

If the system gets compromised you can perform data restore from previous backups.

Finally, don’t forget that no matter how many security measures and contra-measures you take in order to keep your system safe, you will never be 100% completely secure as long as your machine is plugged-in and powered-on.

Enforce Password Complexity Policy On CentOS 7/RHEL Derivatives

In this guide, we are going to learn how to enforce password complexity policy on CentOS 7/RHEL based derivatives. Our previous guide covered the enforcement of password complexity on Ubuntu 18.04. You can check the same by following the link below;

Enforce Password Complexity Policy On CentOS 7

Similar to our previous guide, we are going to use PAM pwquality modules to enforce password complexity policy on CentOS 7/RHEL based derivatives.

In Ubuntu or Debian based derivatives, we modified the, /etc/pam.d/common-password configuration file. For CentOS 7 or similar derivatives, the /etc/security/pwquality.conf or /etc/pam.d/system-auth configuration file is used.

As our normalcy, make a backup of the configuration file before making changes just in case things go south.

cp /etc/security/pwquality.conf /etc/security/pwquality.conf.original
cp /etc/pam.d/system-auth /etc/pam.d/system-auth.original

Open the configuration file for editing.

vim /etc/pam.d/system-auth

Locate the line containing the modules;

password    requisite try_first_pass local_users_only retry=3 authtok_type=

Comment the line and replace by the line below;

password    requisite try_first_pass local_users_only retry=3 authtok_type= minlen=8 lcredit=-1 ucredit=-1 dcredit=-1 ocredit=-1 enforce_for_root


  • minlen=8– sets the minimum password length to 8 characters.
  • lcredit=-1 -Sets the minimum number of lower case letters that the password should contain to at least one
  • ucredit=-1-Sets the minimum number of upper case letters on a password to at least one.
  • dcredit=-1 – Sets the minimum number of digits to be contained in a password to at least one
  • ocredit=-1 – Set the minimum number of other symbols such as @, #, ! $ % etc on a password to at least one
  • enforce_for_root – Ensures that even if it is the root user that is setting the password, the complexity policies should be enforced.

You can also achieve the same by using the authconfig command line utility as shown below;

authconfig --enablereqlower --enablerequpper --enablereqdigit --enablereqother --passminlen=8 --passmaxrepeat=3 --update

The above command basically ensures that password should have at least (in the respective order);

  • one lower case letter
  • one upper case letter
  • one digit
  • an alphanumeric character.
  • 8 characters in length
  • no more than 3 characters similar to the previous password.

The changes will updated on /etc/security/pwquality.conf.

tail /etc/security/pwquality.conf
# Path to the cracklib dictionaries. Default is to use the cracklib default.
# dictpath =
minlen = 8
minclass = 1
maxrepeat = 3
maxclassrepeat = 0
lcredit = -1
ucredit = -1
dcredit = -1
ocredit = -1

Note that root or any user with sudo rights can always set any password irrespective of the enforced policies. However, to ensure that the password complexity policies applies to both root and user with sudo, you must append the enforce_for_root option to the line below on /etc/pam.d/system-auth.

password requisite try_first_pass local_users_only retry=3 authtok_type= enforce_for_root

Testing Password Enforcement Policy

As a root user, try to change the password of a user with a password that doesn’t meet the set credentials.

[root@Cent7 ~]# passwd amos
Changing password for user amos.
New password: @moskifaru1
BAD PASSWORD: The password contains less than 1 uppercase letters
New password: @mosKifaru
BAD PASSWORD: The password contains less than 1 digits
New password: mosKifaru1
BAD PASSWORD: The password contains less than 1 non-alphanumeric characters
passwd: Have exhausted maximum number of retries for service

Test using a more complex password; @mosKifaru1

[root@Cent7 ~]# passwd amos
Changing password for user amos.
New password: @mosKifaru1
Retype new password: @mosKifaru1
passwd: all authentication tokens updated successfully.

That is all about how to enforce password complexity policy on CentOS 7. Enjoy.




  1. PowerShell优化和性能测试
  2. 让你的PowerShell For循环提速四倍
  3. 优化PowerShell的性能和内存消耗
  4. PowerShell提速和多线程
  5. 优化PowerShell脚本的几个小技巧
  6. 轻量级的PowerShell性能测试

本篇文章本是源自PowerShell.Com上的一个教程视频,讲师为Dr. Tobias Weltner。有时间的朋友可以直接去看英文视频。我英文水平有限,还没到达单靠纯听力就能给视频加中文字幕的能力,所以就把原视频中的观点与例子分享出来。




  • 写一个大文件可能需要3.6分钟,提高性能后,只需3秒钟
  • 读一个大文件可能需要77秒钟,提高性能后,只需2秒钟
  • 检查250台机器的是否在线,需要23.2分钟,提高性能后,只需26秒钟








12345678910#这个很快PS> 1..100 |Get-Random90 #这个稍有延迟,可以容忍PS> 1..10000 |Get-Random4868 #这个慢的受不了,所以直接Ctrl-C取消。PS> 1..1000000 |Get-Random


123#这样做,快的一塌糊涂啊PS> Get-Random -InputObject (1..1000000)317486



123$all = @('Some Test' * 20)*1000000$file "$Env:TEMP\testfile.txt"$all Out-File $file

上面的脚本执行大概需要215 秒钟(3.6分钟)

1Out-File $file -InputObject $all


1[Io.file]::WriteAllLines( $file$all,[text.encoding]::Unicode)


1Set-Content $file -Value $all -Encoding Unicode




  1. 不要使用管道。
  2. 不要使用神马的Out-这样的命令(因为它会做格式化)



1Get-Content $file




1Get-Content $file -ReadCount 0


1Get-Content $file -ReadCount 0 | foreach {"X" }


12$text Get-Content $file -ReadCount 0foreach ($line in $text) {'X'}


12$text Get-Content $file -ReadCount 0 | foreach {"X" }$text ForEach-Object {'X'}


  • cmdlet明显非常慢
  • .NET一些底层的方法相对较快


  • 不要轻易引入管道。
  • 尽量使用传统的For或者foreach循环



11..1000000  | ForEach-Object "looping for the $_ Time"}


1234For $x=1; $x -le 100000;$x++){"Looping for the $x. time"}


12345678#耗时0.1毫秒'Hello' |out-null #耗时 0.002毫秒,速度提高了56倍$null'Hello' #耗时0.0025毫秒,速度也很快[void] 'Hello'






12345678910111213$start Get-Date$code1 = { Start-Sleep -Seconds 5; 'A' }$code2 = { Start-Sleep -Seconds 6; 'B'}$code3 = { Start-Sleep -Seconds 7; 'C'} $result1,$result2,$result3= (& $code1),(& $code2),(& $code3) $end =Get-Date$timespan$end $start$seconds $timespan.TotalSeconds Write-Host "总耗时 $seconds 秒."Write-Host "三个脚本块总共延时 18 秒"


总耗时 18.0240865 秒.
三个脚本块总共延时 18 秒


123456789101112131415161718$start Get-Date$code1 = { Start-Sleep -Seconds 5; 'A' }$code2 = { Start-Sleep -Seconds 6; 'B'}$code3 = { Start-Sleep -Seconds 7; 'C'} $job1 Start-Job -ScriptBlock $code1$job2 Start-Job -ScriptBlock $code2$job3 Start-Job -ScriptBlock $code3 $alljobs =  Wait-Job $job1,$job2,$job3$result1,$result2,$result3 Receive-Job $alljobs $end =Get-Date $timespan$end $start$seconds $timespan.TotalSecondsWrite-Host "总耗时 $seconds 秒."Write-Host "三个脚本块总共延时 18 秒"


总耗时 10.3778469 秒.
三个脚本块总共延时 18 秒



  1. 每一个新的任务执行时都会使用一个新PowerShell进程。(所以所谓的多线程并不是真正的多线程,而是工作在进程级别上)
  2. 每一个任务的结果需要序列化后,跨进程传递给调度的主进程。
  3. 没有节流机制(所以要注意控制后台Job的数量)。


1234567891011121314151617181920212223242526272829303132333435363738# (C) 2012 Dr. Tobias Weltner# you may freely use this code for commercial or non-commercial purposes at your own risk# as long as you credit its original author and keep this comment block.# For PowerShell training or PowerShell support, feel free to contact $code = {$begin Get-Date$result Get-Process$end Get-Date $begin$end# play here by reducing the returned data,# i.e. use select-object to pick specific properties:$result} $start Get-Date $job Start-Job -ScriptBlock $code$null Wait-Job $job$completed Get-Date $result Receive-Job $job$received Get-Date $spinup $result[0]$exit $result[1] $timeToLaunch = ($spinup $start).TotalMilliseconds$timeToExit = ($completed $exit).TotalMilliseconds$timeToRunCommand = ($exit $spinup).TotalMilliseconds$timeToReceive = ($received $completed).TotalMilliseconds '{0,-30} : {1,10:#,##0.00} ms' -f 'Time to set up background job'$timeToLaunch'{0,-30} : {1,10:#,##0.00} ms' -f 'Time to run code'$timeToRunCommand'{0,-30} : {1,10:#,##0.00} ms' -f 'Time to exit background job'$timeToExit'{0,-30} : {1,10:#,##0.00} ms' -f 'Time to receive results'$timeToReceive



Time to set up background job  :     270.01 ms
Time to run code               :      10.00 ms
Time to exit background job    :   1,550.06 ms
Time to receive results        :      10.00 ms


Time to set up background job  :     350.01 ms
Time to run code               :      10.00 ms
Time to exit background job    :      10.00 ms
Time to receive results        :       0.00 ms


1$result select-object Name,CPU
Time to set up background job  :     420.02 ms
Time to run code               :      10.00 ms
Time to exit background job    :     100.01 ms
Time to receive results        :       0.00 ms







  • 不需要新的宿主进程
  • 不需要序列化结果
  • 线程内通信方便
  • 运行空间池提供了自动内存节流


PS>  # Running New Thread Synchronously:
PS> $code = { Start-Sleep -Seconds 2; "Hello" }
PS> $newPowerShell = [PowerShell]::Create().AddScript($code)
PS> $newPowerShell.Invoke()


123456789101112$code = {Start-Sleep -Seconds 2; "Hello"} $newPowerShell [PowerShell]::Create().AddScript($code)$handle $newPowerShell.BeginInvoke() while ($handle.IsCompleted -eq $false) {Write-Host '.' -NoNewlineStart-Sleep -Milliseconds 500} Write-Host ''$newPowerShell.EndInvoke($handle)


123456789101112131415161718192021function Start-Progress {param([ScriptBlock]$code) $newPowerShell [PowerShell]::Create().AddScript($code)$handle $newPowerShell.BeginInvoke() while ($handle.IsCompleted -eq $false) {Write-Host '.' -NoNewlineStart-Sleep -Milliseconds 500} Write-Host '' $newPowerShell.EndInvoke($handle) $newPowerShell.Runspace.Close()$newPowerShell.Dispose()}



PS> Start-Progress -code {Get-HotFix}

Source        Description      HotFixID      InstalledBy          InstalledOn
------        -----------      --------      -----------          -----------
ETS-V-TEST-01 Update           KB2899189_... NT AUTHORITY\SYSTEM  5/14/2014 12:00:00 AM
ETS-V-TEST-01 Update           KB2919355     ETS-V-TEST-01\Adm... 3/18/2014 12:00:00 AM
ETS-V-TEST-01 Update           KB2919442     ETS-V-TEST-01\Adm... 3/18/2014 12:00:00 AM
ETS-V-TEST-01 Security Update  KB2920189     NT AUTHORITY\SYSTEM  5/14/2014 12:00:00 AM
ETS-V-TEST-01 Security Update  KB2926765     NT AUTHORITY\SYSTEM  5/15/2014 12:00:00 AM
ETS-V-TEST-01 Security Update  KB2931366     NT AUTHORITY\SYSTEM  5/14/2014 12:00:00 AM


PS> Start-Progress -code {Get-WmiObject -Class Win32_product}
IdentifyingNumber : {90150000-0015-0409-0000-0000000FF1CE}
Name              : Microsoft Access MUI (English) 2013
Vendor            : Microsoft Corporation
Version           : 15.0.4569.1506
Caption           : Microsoft Access MUI (English) 2013

IdentifyingNumber : {90150000-0115-0409-0000-0000000FF1CE}
Name              : Microsoft Office Shared Setup Metadata MUI (English) 2013
Vendor            : Microsoft Corporation
Version           : 15.0.4569.1506
Caption           : Microsoft Office Shared Setup Metadata MUI (English) 2013
123456789101112131415161718192021222324252627function Start-Timebomb {param([Int32]$Seconds, [ScriptBlock]$Action = { Stop-Process -Id $PID }) $Wait "Start-Sleep -seconds $seconds"$script:newPowerShell [PowerShell]::Create().AddScript($Wait).AddScript($Action)$handle $newPowerShell.BeginInvoke()Write-Warning "Timebomb is active and will go off in $Seconds seconds unless you call Stop-Timebomb before."} function Stop-Timebomb {if $script:newPowerShell -ne $null) {Write-Host 'Trying to stop timebomb...' -NoNewline$script:newPowerShell.Stop()$script:newPowerShell.Runspace.Close()$script:newPowerShell.Dispose()Remove-Variable newPowerShell -Scope scriptWrite-Host 'Done!'else {Write-Warning 'No timebomb found.'}}


PS> Start-Timebomb -Seconds 10
WARNING: Timebomb is active and will go off in 10 seconds unless you call Stop-Timebomb before.


1$Wait "1..$seconds | foreach-object {start-sleep -seconds 1;  [console]::Title=""`$($Seconds-`$_) seconds remaining`"}"


123456789101112131415161718192021222324252627282930313233343536373839404142function Start-TimebombMemory {param([Int32]$MemoryMB=30, [ScriptBlock]$Action = { Stop-Process -Id $PID }) $Wait '$initial = (Get-Process -Id $PID).WorkingSet$threshold = (XXX * 1MB)do  {$memory = ((Get-Process -Id $PID).WorkingSet - $initial)Start-Sleep -Seconds 1[system.Console]::Title = ("Current Memory Load: {0:0.00} MB. Threshold: XXX MB" -f ($memory/1MB))} while ($memory -lt $threshold) $message1 = "Shell is using {0:0.0} MB which is exceeding the threshold by {1:0.0} MB." -f ($memory/1MB), (($memory-$threshold)/1MB)$message2 = "Shell will be aborted in 5 seconds. There is nothing you can do about it, sorry."[System.Console]::WriteLine($message1)[System.Console]::WriteLine($message2)Start-Sleep -Seconds 5' -replace 'XXX'$MemoryMB $script:newPowerShellMB [PowerShell]::Create().AddScript($Wait).AddScript($Action)$handle $newPowerShellMB.BeginInvoke()Write-Warning "Timebomb is active and will go off when the shell uses more than $memoryMB MB -  unless you call Stop-Timebomb before."} function Stop-TimebombMemory {if $script:newPowerShellMB -ne $null) {Write-Host 'Trying to stop timebomb...' -NoNewline$script:newPowerShellMB.Stop()$script:newPowerShellMB.Runspace.Close()$script:newPowerShellMB.Dispose()Remove-Variable newPowerShellMB -Scope scriptWrite-Host 'Done!'else {Write-Warning 'No timebomb found.'}}





你写了一个函数,调用winform的OpenFileDialog来打开文件选择对话框。很不幸如果当前的控制台运行在MTA模式下,则对话框不能显示。所以为了增强兼容性,给你的函数单独指定一个线程运行,因为在运行空间中可以指定Apartment State。具体看下面的代码:

1234567891011121314151617181920212223242526272829303132333435363738function Show-OpenFileDialog {param([string]$Title='Select a file',[string]$Path=$home,[string]$Filter "All Files (*.*)|*.*")  $code = {param([string]$Title,[string]$Path,[string]$Filter "All Files (*.*)|*.*") Add-Type -AssemblyName System.Windows.Forms $DialogOpen New-Object System.Windows.Forms.OpenFileDialog$DialogOpen.InitialDirectory = $Path$DialogOpen.Filter $Filter$DialogOpen.Title = $Title$Result $DialogOpen.ShowDialog()if ($Result -eq "OK"){$DialogOpen.FileName}} $newRunspace [RunSpaceFactory]::CreateRunspace()$newRunspace.ApartmentState = 'MTA'$newRunspace.Open()$newPowerShell [PowerShell]::Create()$newPowerShell.Runspace = $newRunspace[void]$newPowerShell.AddScript($code).AddArgument($Title).AddArgument($Path).AddArgument($Filter)$newPowerShell.Invoke()$newPowerShell.Runspace.Close()$newPowerShell.Dispose()}
  • PowerShell:代表线程
  • RunSpace:代表Powershell会话
  • BeginInvoke():返回等待的句柄
  • EndInvoke():返回结果对象
  • MTA和STA模式可以完全控制
  • 每次执行完毕后,记得释放RunSpace,销毁线程。
  1. 创建一个RunSpace 池
  2. 使用RunSpace池代替Runspace
  3. 在池中控制活动的RunSpace个数


12345678910111213141516$throttleLimit = 5$iss []::CreateDefault()$Pool [runspacefactory]::CreateRunspacePool(1, $throttleLimit$iss$Host)$Pool.Open() $ScriptBlock = {param($id)Start-Sleep -Seconds 2[System.Console]::WriteLine("Done processing ID $id")} for ($x = 1; $x -le 40; $x++) {$powershell ::Create().AddScript($ScriptBlock).AddArgument($x)$powershell.RunspacePool = $Pool$handle $powershell.BeginInvoke()}
1234567891011121314151617181920212223242526272829303132333435363738$throttleLimit = 4$SessionState []::CreateDefault()$Pool [runspacefactory]::CreateRunspacePool(1, $throttleLimit$SessionState$Host)$Pool.Open() $ScriptBlock = {param($id) Start-Sleep -Seconds 2"Done processing ID $id"} $threads = @() $handles for ($x = 1; $x -le 40; $x++) {$powershell ::Create().AddScript($ScriptBlock).AddArgument($x)$powershell.RunspacePool = $Pool$powershell.BeginInvoke()$threads += $powershell} do {$i = 0$done $trueforeach ($handle in $handles) {if ($handle -ne $null) {if ($handle.IsCompleted) {$threads[$i].EndInvoke($handle)$threads[$i].Dispose()$handles[$i] = $nullelse {$done $false}}$i++}if (-not $done) { Start-Sleep -Milliseconds 500 }until ($done)

声明:本文所有观点,图片,示例脚本引用自 Dr. Tobias Weltner的视频教程。感谢 Dr. Tobias Weltner!
视频出处Speeding Up PowerShell (网盘:密码: 7w21 )


iCACLS.exe (2003 sp2, Vista+)

Change file and folder permissions – display or modify Access Control Lists (ACLs) for files and folders.
iCACLS resolves various issues that occur when using the older CACLS & XCACLS

   Add or remove permissions:
      ICACLS Name
         [/grant[:r] User:Permission[...]]
            [/deny User:Permission[...]]
               [/remove[:g|:d]] User[...]]
                  [/inheritance:e|d|r ]
                     [/setintegritylevel Level[...]]
                        [/T] [/C] [/L] [/Q]

   Store ACLs for one or more directories matching name into aclfile for later use with /restore:
      ICACLS name /save aclfile [/T] [/C] [/L] [/Q]
   Restore ACLs to all files in directory:
      ICACLS directory [/substitute SidOld SidNew [...]]
          /restore aclfile [/C] [/L] [/Q]

   Change Owner:
      ICACLS name /setowner user [/T] [/C] [/L] [/Q]

   Find items with an ACL that mentions a specific SID:
      ICACLS name /findsid Sid [/T] [/C] [/L] [/Q]

   Find files whose ACL is not in canonical form or with a length inconsistent with the ACE count:
      ICACLS name /verify [/T] [/C] [/L] [/Q]
   Replace ACL with default inherited acls for all matching files:
      ICACLS name /reset [/T] [/C] [/L] [/Q]
   This is equivalent to “Replace all child permission entries with inheritable permission from this object” in the GUI.

   name  The File(s) or folder(s) the permissions will apply to.

   /T  Traverse all subfolders to match files/directories. This will apply permission changes to
       all subfolders whether or not they are set to inherit permissions from the parent. On very large
       directory structures this may take some time as the command has to traverse the entire tree.
   /C  Continue on file errors (access denied) Error messages are still displayed.
   /L  Perform the operation on a symbolic link itself, not its target.

   /Q  Quiet - supress success messages.

   /grant :r user:permission
       Grant access rights, with :r, the permissions
       will replace any previouly granted explicit permissions (for the given user).
       Otherwise the permissions are added.

   /deny user:permission
       Explicitly deny the specified user access rights.
       This will also remove any explicit grant of the 
       same permissions to the same user.

   /remove[:[g|d]] User 
       Remove all occurrences of User from the acl. 
       :g remove all granted rights to that User/Sid.
       :d remove all denied rights to that User/Sid.

          e - Enable inheritance
          d - Disable inheritance and copy the ACEs 
          r - Remove all inherited ACEs

   /setintegritylevel [(CI)(OI)]Level 
       Add an integrity ACE to all matching files. 
       level is one of L,M,H (Low Medium or High)

             Mandatory Label\Low Mandatory Level    = Low.
             Mandatory Label\Medium Mandatory Level = Medium/Standard.
             Mandatory Label\High Mandatory Level   = Elevated.

             If No mandatory label is displayed in the output, it is Medium by default. 

       A Directory Inheritance option for the integrity ACE can precede the level
       and is applied only to directories:

   user   A user account, Group or a SID

   /restore  Apply the acls stored in ACLfile to the files in directory

   permission is a permission mask and can be specified in one of two forms:
        a sequence of simple rights:
                D - Delete access
                F - Full access (Edit_Permissions+Create+Delete+Read+Write)
                N - No access
                M - Modify access (Create+Delete+Read+Write)
                RX - Read and eXecute access
                R - Read-only access
                W - Write-only access
        a comma-separated list in parentheses of specific rights:
                DE - Delete
                RC - read control
                WDAC - write DAC
                WO - write owner
                S - synchronize
                AS - access system security
                MA - maximum allowed
                GR - generic read
                GW - generic write
                GE - generic execute
                GA - generic all
                RD - read data/list directory
                WD - write data/add file
                AD - append data/add subdirectory
                REA - read extended attributes
                WEA - write extended attributes
                X - execute/traverse
                DC - delete child
                RA - read attributes
                WA - write attributes
        inheritance rights can precede either form and are applied
        only to directories:
                (OI) - object inherit
                (CI) - container inherit
                (IO) - inherit only
                (NP) - don’t propagate inherit
                (I)  - Permission inherited from parent container

Unlike earlier command-line tools, iCACLS correctly preserves the canonical ordering of ACE entries:

  1. Explicit Deny
  2. Explicit Grant
  3. Inherited Deny
  4. Inherited Grant

Access Control Lists apply only to files stored on an NTFS formatted drive, each ACL determines which users (or groups of users) can read or edit the file. When a new file is created it normally inherits ACL’s from the folder where it was created.

An access control list (ACL) is a list of access control entries (ACE). When backing up or restoring an ACL with iCACLS, you must do so for an entire directory (using /save and /restore) even if you are only interested in the ACEs for a few individual files. In practice most permissions are set at the per-directory level.

Multiple /Grant /Deny /Remove clauses can be included in a single icacls command, on a large directory tree this has the advantage that the tree only has to be traversed once, rather than multiple times if you were to issue several consecutive icacls commands instead.

Modify vs Full control

  • To edit a file you must have the “Modify/Change” ACL (or be the file’s owner)
  • To use the iCACLS command to change the permissions of a file requires “FULL Control” (or be the file’s owner)
  • File “Ownership” will always override all ACL’s – you always have Full Control over files that you create.


Inherited folder permissions are given as:

 OI - Object inherit    - This folder and files. (no inheritance to subfolders)
 CI - Container inherit - This folder and subfolders.
 IO - Inherit only      - The ACE does not apply to the current file/directory

These can also be combined as follows:
 (OI)(CI)      This folder, subfolders, and files.
 (OI)(CI)(IO)  Subfolders and files only.
     (CI)(IO)  Subfolders only.
 (OI)    (IO)  Files only. 

So BUILTIN\Administrators:(OI)(CI)F means that both files and Subdirectories will inherit ‘F’ (Full control)
similarly (CI)R means Directories will inherit ‘R’ (Read folders only = List permission)

It is worth spending some time working out which permissions can be inherited and which need to be applied directly. On large/complex directory structures, minimising the number of ACLs can improve fileserver performance.

If inheritance is combined with /T (traverse subfolders) the change will apply to all folders, not just the top level.
for example:
icacls “C:\demo\example” /inheritance:e /T
Will traverse all subfolders below”C:\demo\example” and enable the inheritance for every one, this will replace any inheritance permissions that have been removed.

If no inheritance is specified, inheritance rules will not be changed but existing inherited permissions will be re-applied to existing objects in the specified location for the specified users/groups.
for example:
icacls “C:\demo\example” /grant administrators:(F) /T
This is similar to applying /reset to the child items of “C:\demo\example” but only resets the administrators group.

Built-In Groups

A command which addresses a built-in group by name like ICACLS foldername /GRANT Everyone:F /T
will only work when the system language is English.

To make this language independent, use an asterisk followed by the well-known SID for the group, see Q243330 for a list.

For example, to grant full control to Everyone on a folder: ICACLS foldername /GRANT *S-1-1-0:F /T

Running icacls under PowerShell

The options for icacls do not always run easily under PowerShell, but they can be made to work by setting a few variables and then executing with Invoke-Expression to expand all the variables:

#set PS variables for each of the icacls options
$Path = "c:\demo"   #The path must be the first thing passed to icacls
$Grant = "/grant:r"
$Remove = "/remove"
$replaceInherit = "/inheritance:r"
$permission = ":(OI)(CI)(F)"
$useraccount1 = "ss64dom\simon"
$useraccount2 = "administrators"
#run icacls using invoke Expression
Invoke-Expression -Command ('icacls $Path $replaceInherit $Grant "${useraccount1}${permission }"')


Change the NTFS permissions on C:\demo\example\, remove all existing inherited permissions and replace with Full control for the Administrators group and Change/Modify permission for jsmith.
Apply the new permissions to the folder and inherit down to subfolders and files (OI)(CI):

icacls “C:\demo\example” /inheritance:r /grant:r Administrators:(OI)(CI)F
icacls “C:\demo\example” /grant:r Administrators:(OI)(CI)F /T
icacls “C:\demo\example” /grant:r ss64Dom\jsmith:(OI)(CI)M /T

or you can combine grants like:

icacls "C:\demo\example" /grant:r Administrators:(OI)(CI)F /T /grant:r ss64Dom\jsmith:(OI)(CI)M /T

View the permissions currently set on a folder:

icacls “C:\demo\example”

Grant the group FileAdmins ‘Delete’ and ‘Write DAC‘ permissions to C:\demo\example:

icacls “C:\demo\example” /grant:r FileAdmins:(D,WDAC)

Reset permissions on all child items below C:\demo\example\, note the use of \*, without that, the permissions would be reset to those of C:\demo\

icacls “C:\demo\example\*” /c /t /reset

Propagate a new permission to all files and subfolders of C:\demo\example\, without using inheritance:
(so if any of the subfolders contain specific permissions, those won’t be overwritten)

icacls “C:\demo\example” /grant:r accountName:(NP)(RX) /T

Backup the ACLs of every file in the current directory:

icacls * /save Myacl_backup.txt

Restore ACLS using a previously saved acl file:

icacls /restore Myacl_backup.txt

Change the Integrity Level (IL) of a file to High:

icacls MyReport.doc /setintegritylevel H

Remove all inheritance on the ‘Demo’ folder and grant access to the domain user ‘Volta’, in this command the /t will traverse existing subfolders and files, and the (CI) will ensure that new folders/files added in future will inherit these permissions:

icacls C:\demo\example /inheritance:r /grant SS64dom\Volta:(CI)F /t

Grant the user jdoe rights to create, edit and delete files in the folder C:\demo\example\, but prevent deletion of the folder itself:

:: First remove inheritance and grant admins Full control to the top folder
icacls “C:\demo\example” /inheritance:r /grant:r administrators:(OI)(CI)(F)

:: Grant Modify + Delete Child to subfolders and files only
icacls “C:\demo\example” /grant:r ss64Dom\jdoe:(OI)(CI)(IO)(M,DC) /T

:: Grant Read/Execute, Write and Append to the top level folder
icacls “C:\demo\example” /grant:r ss64Dom\jdoe:(RX,WD,AD)

:: if any pre-existing subfolders Grant admins Full control
icacls “C:\demo\example” /grant:r administrators:(OI)(CI)(F) /T

The above does set the correct permissions, but an undesired bug/side effect is that within the top level folder the Windows Explorer right click option to create New files will be empty – only New Folder is shown:

Right Click - New is empty

Linux下进程/程序网络带宽占用情况查看工具 — NetHogs





NetHogs是一个小型的net top工具,不像大多数工具那样拖慢每个协议或者是每个子网的速度而是按照进程进行带宽分组。NetHogs不需要依赖载入某个特殊的内核模块。如果发生了网络阻塞你可以启动NetHogs立即看到哪个PID造成的这种状况。这样就很容易找出哪个程序跑飞了然后突然占用你的带宽。



# yum install nethogs

在Ubuntu、Linux mint和Debian下安装NetHogs

$ sudo apt-get install nethogs


# nethogs

在Debian/Ubuntu/Linux Mint下要执行NetHogs你必须拥有root权限:
$ sudo nethogs


Ubuntu 12.10 下的NetHogs预览


NetHogs 命令行参数

以下就是NetHogs命令行的参数,用-d来添加刷新频率参数,device name 用来检测给定的某个或者某些设备的带宽(默认是eth0)。例如:设置5秒钟的刷新频率,键入如下命令即可:
# nethogs -d 5

$ sudo nethogs -d 5

# nethogs eth0

$ sudo nethogs eth0

# nethogs eth0 eth1

$ sudo nethogs eth0 eth1

-d : 刷新间隔
-h : 帮助
-p : promiscious 模式
-t : trace模式
-V : 版本


• m : 修改单位
• r : 按流量排序
• s : 按发送流量排序
• q : 退出命令提示符

关于NetHogs命令行工具的完整参数列表,可以参考NetHogs的手册,使用方法是在终端里输入man nethogs或者sudo man nethogs,更多信息请参考NetHogs项目主页

之前VPS侦探曾经介绍过流量带宽相关的工具如:iftop、vnstat,这几个都是统计和监控网卡流量的。但是当我们的服务器或 VPS的带宽被大量占用或占满,却没找不到称心的工具或程序来查看到底是哪个程序或进程占有率多少带宽。虽然在Windows上查看进程占用带宽情况的软件很多,像某3**、某Q家的电脑管家、IP雷达等。但是Linux下这一类软件很少,今天我们介绍的就是Linux的一款查看进程带宽网络占用的软件:NetHogs。

Debian/Ubuntu下安装很简单,执行:apt-get install nethogs 就可以安装。

CentOS/RHEL下建议先安装上EPEL,再执行:yum install libpcap nethogs 进行安装。


[root@vpser ~]# nethogs -h
usage: nethogs [-V] [-b] [-d seconds] [-t] [-p] [device [device [device …]]] //nethogs可以使用的参数
-V : prints version.//打印版本信息
-d : delay for update refresh rate in seconds. default is 1. //延迟刷新时间,单位秒,默认1秒
-t : tracemode. //跟踪模式
-b : bughunt mode – implies tracemode. //bughunt模式
-p : sniff in promiscious mode (not recommended). //混合模式下嗅探,不推荐
device : device(s) to monitor. default is eth0 //监听的设备,默认是eth0,也就是网卡设备名称,如果是openvz的vps一般都是venet0,具体可以ifconfig进行查看,lo为本地回环,用不到。多个网卡可以一块写上,空格隔开。

When nethogs is running, press: //nethogs运行是可以使用以下按键进行操作
q: quit //运行时,按 q 键退出
m: switch between total and kb/s mode //按 m 键,切换单位或显示进程占用速度或已统计使用的流量。切换顺序是KB/sec->KB->B->MB
r : Sort by received. //按received进行排序
s : Sort by sent. //按send进行排序

使用例子:nethogs venet0


lsof -i:被占用的端口号 如: lsof -i:80

ps aux|grep PID

DEV列显示设备名,SEND是服务器发送的流量,RECEIVED服务器接收的流量。 // 按 m 可以切换统计方式 : 流量速度KB/sec 或 总数{KB /B /m}