我的 motd 脚本使用 run-parts 可以工作,但通过 ssh 登录时没有输出

我的 motd 脚本使用 run-parts 可以工作,但通过 ssh 登录时没有输出

这是我的00-motd (-rwxr-xr-x)文件:

#!/usr/bin/env python3

DISK_A = '/dev/sda2'
DISK_B = '/dev/sdb1'

import locale
locale.setlocale(locale.LC_TIME, 'pl_PL.UTF-8')

# https://github.com/maxogden/cool-ascii-faces
cool = [
  u"( .-. )",
  u"( .o.)",
  u"( `·´ )",
  u"( ° ͜ ʖ °)",
  u"( ͡° ͜ʖ ͡°)",
  u"( ⚆ _ ⚆ )",
  u"( ︶︿︶)",
  u"( ゚ヮ゚)",
  u"(\\/)(°,,,°)(\\/)",
  u"(¬_¬)",
  u"(¬º-°)¬",
  u"(¬‿¬)",
  u"(°ロ°)☝",
  u"(´・ω・)っ",
  u"(ó ì_í)",
  u"(ʘᗩʘ')",
  u"(ʘ‿ʘ)",
  u"(̿▀̿ ̿Ĺ̯̿̿▀̿ ̿)̄",
  u"(͡° ͜ʖ ͡°)",
  u"ᕦ( ͡° ͜ʖ ͡°)ᕤ",
  u"(ಠ_ಠ)",
  u"(ಠ‿ಠ)",
  u"(ಠ⌣ಠ)",
  u"(ಥ_ಥ)",
  u"(ಥ﹏ಥ)",
  u"(ง ͠° ͟ل͜ ͡°)ง",
  u"(ง ͡ʘ ͜ʖ ͡ʘ)ง",
  u"(ง •̀_•́)ง",
  u"(ง'̀-'́)ง",
  u"(ง°ل͜°)ง",
  u"(ง⌐□ل͜□)ง",
  u"(ღ˘⌣˘ღ)",
  u"(ᵔᴥᵔ)",
  u"(•ω•)",
  u"(•◡•)/",
  u"(⊙ω⊙)",
  u"(⌐■_■)",
  u"(─‿‿─)",
  u"(╯°□°)╯",
  u"(◕‿◕)",
  u"(☞゚∀゚)☞",
  u"(❍ᴥ❍ʋ)",
  u"(っ◕‿◕)っ",
  u"(づ。◕‿‿◕。)づ",
  u"(ノಠ益ಠ)ノ",
  u"(ノ・∀・)ノ",
  u"(;一_一)",
  u"(`◔ ω ◔´)",
  u"(。◕‿‿◕。)",
  u"(ノ◕ヮ◕)ノ",
  u"*<{:¬{D}}}",
  u"=^.^=",
  u"t(-.-t)",
  u"| (• ◡•)|",
  u"~(˘▾˘~)",
  u"¬_¬",
  u"¯(°_o)/¯",
  u"¯\\_(ツ)_/¯",
  u"°Д°",
  u"ɳ༼ຈل͜ຈ༽ɲ",
  u"ʅʕ•ᴥ•ʔʃ",
  u"ʕ´•ᴥ•`ʔ",
  u"ʕ•ᴥ•ʔ",
  u"ʕ◉.◉ʔ",
  u"ʕㅇ호ㅇʔ",
  u"ʕ;•`ᴥ•´ʔ",
  u"ʘ‿ʘ",
  u"͡° ͜ʖ ͡°",
  u"ζ༼Ɵ͆ل͜Ɵ͆༽ᶘ",
  u"Ѱζ༼ᴼل͜ᴼ༽ᶘѰ",
  u"ب_ب",
  u"٩◔̯◔۶",
  u"ಠ_ಠ",
  u"ಠoಠ",
  u"ಠ~ಠ",
  u"ಠ‿ಠ",
  u"ಠ⌣ಠ",
  u"ಠ╭╮ಠ",
  u"ರ_ರ",
  u"ง ͠° ل͜ °)ง",
  u"๏̯͡๏﴿",
  u"༼ ºººººل͟ººººº ༽",
  u"༼ ºل͟º ༽",
  u"༼ ºل͟º༼",
  u"༼ ºل͟º༽",
  u"༼ ͡■ل͜ ͡■༽",
  u"༼ つ ◕_◕ ༽つ",
  u"༼ʘ̚ل͜ʘ̚༽",
  u"ლ(´ڡ`ლ)",
  u"ლ(́◉◞౪◟◉‵ლ)",
  u"ლ(ಠ益ಠლ)",
  u"ᄽὁȍ ̪őὀᄿ",
  u"ᔑ•ﺪ͟͠•ᔐ",
  u"ᕕ( ᐛ )ᕗ",
  u"ᕙ(⇀‸↼‶)ᕗ",
  u"ᕙ༼ຈل͜ຈ༽ᕗ",
  u"ᶘ ᵒᴥᵒᶅ",
  u"(ノಥ益ಥ)ノ",
  u"≧☉_☉≦",
  u"⊙▃⊙",
  u"⊙﹏⊙",
  u"┌( ಠ_ಠ)┘",
  u"╚(ಠ_ಠ)=┐",
  u"◉_◉",
  u"◔ ⌣ ◔",
  u"◔̯◔",
  u"◕‿↼",
  u"◕‿◕",
  u"☉_☉",
  u"☜(⌒▽⌒)☞",
  u"☼.☼",
  u"♥‿♥",
  u"⚆ _ ⚆",
  u"✌(-‿-)✌",
  u"〆(・∀・@)",
  u"ノ( º _ ºノ)",
  u"ノ( ゜-゜ノ)",
  u"ヽ( ͝° ͜ʖ͡°)ノ",
  u"ヽ(`Д´)ノ",
  u"ヽ༼° ͟ل͜ ͡°༽ノ",
  u"ヽ༼ʘ̚ل͜ʘ̚༽ノ",
  u"ヽ༼ຈل͜ຈ༽ง",
  u"ヽ༼ຈل͜ຈ༽ノ",
  u"ヽ༼Ὸل͜ຈ༽ノ",
  u"ヾ(⌐■_■)ノ",
  u"꒰・◡・๑꒱",
  u"﴾͡๏̯͡๏﴿",
  u"。◕‿◕。",
  u"ʕノ◔ϖ◔ʔノ",
  u"(ノಠ益ಠ)ノ彡┻━┻",
  u"(╯°□°)╯︵ ┻━┻",
  u"꒰•̥̥̥̥̥̥̥ ﹏ •̥̥̥̥̥̥̥̥๑꒱",
  u"ಠ_ರೃ",
  u"(ू˃̣̣̣̣̣̣︿˂̣̣̣̣̣̣ ू)",
  u"(ꈨຶꎁꈨຶ)۶”",
  u"(ꐦ°᷄д°᷅)",
  u"(۶ૈ ۜ ᵒ̌▱๋ᵒ̌ )۶ૈ=͟͟͞͞ ⌨",
  u"₍˄·͈༝·͈˄₎◞ ̑̑ෆ⃛",
  u"(*゚⚙͠ ∀ ⚙͠)ノ❣",
  u"٩꒰・ัε・ั ꒱۶",
  u"ヘ(。□°)ヘ",
  u"˓˓(ृ  ु ॑꒳’)ु(ृ’꒳ ॑ ृ )ु˒˒˒",
  u"꒰✘Д✘◍꒱",
  u"૮( ᵒ̌ૢཪᵒ̌ૢ )ა",
  u"“ψ(`∇´)ψ",
  u"ಠﭛಠ",
  u"(๑>ᴗ<๑)",
  u"(۶ꈨຶꎁꈨຶ )۶ʸᵉᵃʰᵎ",
  u"٩(•̤̀ᵕ•̤́๑)ᵒᵏᵎᵎᵎᵎ",
  u"(oT-T)尸",
  u"(✌゚∀゚)☞",
  u"ಥ‿ಥ",
  u"ॱ॰⋆(˶ॢ‾᷄﹃‾᷅˵ॢ)",
  u"┬┴┬┴┤  (ಠ├┬┴┬┴",
  u"( ˘ ³˘)♥",
  u"Σ (੭ु ຶਊ ຶ)੭ु⁾⁾",
  u"(⑅ ॣ•͈ᴗ•͈ ॣ)",
  u"ヾ(´¬`)ノ",
  u"(•̀o•́)ง",
  u"(๑•॒̀ ູ॒•́๑)",
  u"⚈้̤͡ ˌ̫̮ ⚈้̤͡",
  u"=͟͟͞͞ =͟͟͞͞ ヘ( ´Д`)ノ",
  u"(((╹д╹;)))",
  u"•̀.̫•́✧",
  u"(ᵒ̤̑ ₀̑ ᵒ̤̑)",
  u"\\_(ʘ_ʘ)_/",
  u"乙(ツ)乙",
  u"乙(のっの)乙",
  u"ヾ(¯∇ ̄๑)",
  u"\\_(ʘ_ʘ)_/",
  u"༼;´༎ຶ ۝ ༎ຶ༽",
  u"(▀̿Ĺ̯▀̿ ̿)",
  u"(ノ◕ヮ◕)ノ*:・゚✧",
  u"(ノ◕ヮ◕)ノ*:・゚✧ ✧゚・: *ヽ(◕ヮ◕ヽ)",
  u"┬┴┬┴┤ ͜ʖ ͡°) ├┬┴┬┴",
  u"┬┴┬┴┤(・_├┬┴┬┴",
  u"(͡ ͡° ͜ つ ͡͡°)",
  u"( ͡°╭͜ʖ╮͡° )",
  u"(• ε •)",
  u"[̲̅$̲̅(̲̅ ͡° ͜ʖ ͡°̲̅)̲̅$̲̅]",
  u"| (• ◡•)| (❍ᴥ❍ʋ)",
  u"(◕‿◕✿)",
  u"(╯°□°)╯︵ ʞooqǝɔɐɟ",
  u"(☞゚ヮ゚)☞ ☜(゚ヮ゚☜)",
  u"(づ ̄ ³ ̄)づ",
  u"(;´༎ຶД༎ຶ`)",
  u"♪~ ᕕ(ᐛ)ᕗ",
  u"༼ つ  ͡° ͜ʖ ͡° ༽つ",
  u"༼ つ ಥ_ಥ ༽つ",
  u"ಥ_ಥ",
  u"( ͡ᵔ ͜ʖ ͡ᵔ )",
  u"ヾ(⌐■_■)ノ♪",
  u"~(˘▾˘~)",
  u"\\ (•◡•) /",
  u"(~˘▾˘)~",
  u"(._.) ( l: ) ( .-. ) ( :l ) (._.)",
  u"༼ ºل͟º ༼ ºل͟º ༼ ºل͟º ༽ ºل͟º ༽ ºل͟º ༽",
  u"┻━┻ ︵ヽ(`Д´)ノ︵ ┻━┻",
  u"ᕦ(ò_óˇ)ᕤ",
  u"(•_•) ( •_•)>⌐■-■ (⌐■_■)",
  u"(☞ຈل͜ຈ)☞",
  u"˙ ͜ʟ˙",
  u"☜(˚▽˚)☞",
  u"(。◕‿◕。)",
  u"(╯°□°)╯︵( .o.)",
  u"(っ˘ڡ˘ς)",
  u"┬──┬ ノ( ゜-゜ノ)",
  u"ಠ⌣ಠ",
  u"( ಠ ͜ʖರೃ)",
  u"ƪ(˘⌣˘)ʃ",
  u"¯\\(°_o)/¯",
  u"ლ,ᔑ•ﺪ͟͠•ᔐ.ლ",
  u"(´・ω・`)",
  u"(´・ω・)っ由",
  u"(° ͡ ͜ ͡ʖ ͡ °)",
  u"Ƹ̵̡Ӝ̵̨̄Ʒ",
  u"ಠ_ಥ",
  u"ಠ‿↼",
  u"(>ლ)",
  u"(▰˘◡˘▰)",
  u"(✿´‿`)",
  u"◔ ⌣ ◔",
  u"。゜(`Д´)゜。",
  u"┬─┬ノ( º _ ºノ)",
  u"(ó ì_í)=óò=(ì_í ò)",
  u"(/) (°,,°) (/)",
  u"┬─┬ ︵ /(.□. )",
  u"^̮^",
  u"(>人<)",
  u"(~_^)",
  u"(・.◤)",
  u">_>",
  u"(^̮^)",
  u"=U",
  u"(。╹ω╹。)",
  u"ლ(╹◡╹ლ)",
  u"(●´⌓`●)",
  u"([∂]ω[∂])",
  u"U^エ^U",
  u"(〒ó〒)",
  u"(T^T)",
  u"(íoì)",
  u"(#•v•#)",
  u"(•^u^•)",
  u"!(^3^)!",
  u"\\(°°\\”)",
  u"(°o°:)",
  u"(° o°)!",
  u"(oロo)!!",
  u"(òロó)",
  u"(ò皿ó)",
  u"( ̄・_______・ ̄)",
  u"ヾ(๑╹◡╹)ノ'",
  u"(ლ╹◡╹)ლ",
  u"(◞‸◟)",
  u"(✿◖◡◗)",
  u"( ´・‿・`)",
  u"(*`益´*)がう",
  u"(ヾノ'д'o)ナィナィ",
  u"❤(◕‿◕✿)",
  u"(◡‿◡*)❤",
  u"(o'ω'o)",
  u"(。・ˇ_ˇ・。)ムゥ…",
  u"♬♩♫♪☻(●´∀`●)☺♪♫♩♬",
  u"(✿ฺ◕ฺ‿◕ฺ)ウフッ♥",
  u"(つД⊂)エーン",
  u"(つД・)チラ",
  u"(*´ω`*)",
  u"(✪‿✪)ノ",
  u"╲(。◕‿◕。)╱",
  u"ლ(^o^ლ)"
]

import random
r = random.SystemRandom()
cool_choice = r.choice(cool)

import time as t
time = t.strftime('%H:%M')
date = t.strftime('%A %d %B %Y').title()

import multiprocessing
cores = multiprocessing.cpu_count()

uptime = 0
idletime = 0
load = ''

with open('/proc/uptime', 'r') as f:
  s = f.readline().split()
  uptime = float(s[0])
  idletime = float(s[1])

with open('/proc/loadavg', 'r') as f:
  s = f.readline().split()
  load = (s[0] + ', ' + s[1] + ', ' + s[2]).rjust(28, ' ')
  processes = (s[3]).rjust(23, ' ')

import pendulum
uptime_for_humans = pendulum.duration(minutes=uptime // 60).in_words()
idle_percentage = '%.2f' % round(idletime / cores / uptime * 100, 2)

uptime_gui = uptime_for_humans + (idle_percentage + ' % idling').rjust(72 - len(uptime_for_humans), ' ')

import psutil
memory = psutil.virtual_memory()
partitions = psutil.disk_partitions()

disk_a_dev = '/'
disk_a = psutil.disk_usage('/')
disk_b_dev = '/'
disk_b = psutil.disk_usage('/')

for partition in partitions:
  if DISK_A == partition.device:
    disk_a_dev = partition.device
    disk_a = psutil.disk_usage(partition.mountpoint)
  if DISK_B == partition.device:
    disk_b_dev = partition.device
    disk_b = psutil.disk_usage(partition.mountpoint)

def bytes_for_humans(b, ndigits=2):
  units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'] # Powodzenia kurwa
  depth = 0
  value = b

  while (value // 1024):
    depth += 1
    value /= 1024

  if depth:
    value = ('%.2f' % round(value, ndigits))

  return str(value) + ' ' + units[depth]

disk_a_data = [
  ('%.2f' % round(disk_a.used / disk_a.total * 100, 2)).rjust(32 - len(disk_a_dev), ' '),
  bytes_for_humans(disk_a.total).rjust(27, ' '),
  bytes_for_humans(disk_a.free).rjust(27, ' '),
  bytes_for_humans(disk_a.used).rjust(27, ' ')
]

disk_b_data = [
  ('%.2f' % round(disk_b.used / disk_b.total * 100, 2)).rjust(32 - len(disk_b_dev), ' '),
  bytes_for_humans(disk_b.total).rjust(27, ' '),
  bytes_for_humans(disk_b.free).rjust(27, ' '),
  bytes_for_humans(disk_b.used).rjust(27, ' ')
]

mem_data = [
  ('%.2f' % round(memory.used / memory.total * 100, 2)).rjust(20, ' '),
  bytes_for_humans(memory.total).rjust(23, ' '),
  bytes_for_humans(memory.available).rjust(23, ' '),
  bytes_for_humans(memory.free).rjust(23, ' '),
  bytes_for_humans(memory.used).rjust(23, ' ')
]

print(f'''
  ┌─┐┬ ┬┌┐ ┌─┐┬─┐┌─┐┌─┐┬ ┬┬┬
  └─┐│ │├┴┐├─┤├┬┘├─┤└─┐├─┤││  {time}
  └─┘└─┘└─┘┴ ┴┴└─┴ ┴└─┘┴ ┴┴┴  {date}

  {cool_choice}


  ┌ Uptime ──────────────────────────────────────────────────────────────────┐  
  │ {uptime_gui                                                            } │  
  └──────────────────────────────────────────────────────────────────────────┘  
  ┌ System ────────────────────────────┐┌ Partitions ────────────────────────┐  
  │ Load: {load                      } ││ {disk_a_dev + disk_a_data[0]   } % │  
  │ Processes: {processes            } ││ Total: {disk_a_data[1]           } │  
  └────────────────────────────────────┘│ Free:  {disk_a_data[2]           } │  
  ┌ Memory ────────────────────────────┐│ Used:  {disk_a_data[3]           } │  
  │ Percentage: {mem_data[0]       } % │├────────────────────────────────────┤  
  │ Total:     {mem_data[1]          } ││ {disk_b_dev + disk_b_data[0]   } % │  
  │ Available: {mem_data[2]          } ││ Total: {disk_b_data[1]           } │  
  │ Free:      {mem_data[3]          } ││ Free:  {disk_b_data[2]           } │  
  │ Used:      {mem_data[4]          } ││ Used:  {disk_b_data[3]           } │  
  └────────────────────────────────────┘└────────────────────────────────────┘  
''')

这是输出run-parts /etc/update-motd.d

运行部件输出

这是/etc/pam.d/login

#
# The PAM configuration file for the Shadow `login' service
#

# Enforce a minimal delay in case of failure (in microseconds).
# (Replaces the `FAIL_DELAY' setting from login.defs)
# Note that other modules may require another minimal delay. (for example,
# to disable any delay, you should add the nodelay option to pam_unix)
auth       optional   pam_faildelay.so  delay=3000000

# Outputs an issue file prior to each login prompt (Replaces the
# ISSUE_FILE option from login.defs). Uncomment for use
# auth       required   pam_issue.so issue=/etc/issue

# Disallows root logins except on tty's listed in /etc/securetty
# (Replaces the `CONSOLE' setting from login.defs)
#
# With the default control of this module:
#   [success=ok new_authtok_reqd=ok ignore=ignore user_unknown=bad default=die]
# root will not be prompted for a password on insecure lines.
# if an invalid username is entered, a password is prompted (but login
# will eventually be rejected)
#
# You can change it to a "requisite" module if you think root may mis-type
# her login and should not be prompted for a password in that case. But
# this will leave the system as vulnerable to user enumeration attacks.
#
# You can change it to a "required" module if you think it permits to
# guess valid user names of your system (invalid user names are considered
# as possibly being root on insecure lines), but root passwords may be
# communicated over insecure lines.
auth [success=ok new_authtok_reqd=ok ignore=ignore user_unknown=bad default=die] pam_securetty.so

# Disallows other than root logins when /etc/nologin exists
# (Replaces the `NOLOGINS_FILE' option from login.defs)
auth       requisite  pam_nologin.so

# SELinux needs to be the first session rule. This ensures that any
# lingering context has been cleared. Without this it is possible
# that a module could execute code in the wrong domain.
# When the module is present, "required" would be sufficient (When SELinux
# is disabled, this returns success.)
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close

# Sets the loginuid process attribute
session    required     pam_loginuid.so

# SELinux needs to intervene at login time to ensure that the process
# starts in the proper default security context. Only sessions which are
# intended to run in the user's context should be run after this.
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open
# When the module is present, "required" would be sufficient (When SELinux
# is disabled, this returns success.)

# This module parses environment configuration file(s)
# and also allows you to use an extended config
# file /etc/security/pam_env.conf.
# 
# parsing /etc/environment needs "readenv=1"
session       required   pam_env.so readenv=1
# locale variables are also kept into /etc/default/locale in etch
# reading this file *in addition to /etc/environment* does not hurt
session       required   pam_env.so readenv=1 envfile=/etc/default/locale

# Standard Un*x authentication.
@include common-auth

# This allows certain extra groups to be granted to a user
# based on things like time of day, tty, service, and user.
# Please edit /etc/security/group.conf to fit your needs
# (Replaces the `CONSOLE_GROUPS' option in login.defs)
auth       optional   pam_group.so

# Uncomment and edit /etc/security/time.conf if you need to set
# time restraint on logins.
# (Replaces the `PORTTIME_CHECKS_ENAB' option from login.defs
# as well as /etc/porttime)
# account    requisite  pam_time.so

# Uncomment and edit /etc/security/access.conf if you need to
# set access limits.
# (Replaces /etc/login.access file)
# account  required       pam_access.so

# Sets up user limits according to /etc/security/limits.conf
# (Replaces the use of /etc/limits in old login)
session    required   pam_limits.so

# Prints the last login info upon successful login
# (Replaces the `LASTLOG_ENAB' option from login.defs)
session    optional   pam_lastlog.so

# Prints the message of the day upon successful login.
# (Replaces the `MOTD_FILE' option in login.defs)
# This includes a dynamically generated part from /run/motd.dynamic
# and a static (admin-editable) part from /etc/motd.
session    optional   pam_motd.so motd=/run/motd.dynamic
session    optional   pam_motd.so noupdate

# Prints the status of the user's mailbox upon successful login
# (Replaces the `MAIL_CHECK_ENAB' option from login.defs). 
#
# This also defines the MAIL environment variable
# However, userdel also needs MAIL_DIR and MAIL_FILE variables
# in /etc/login.defs to make sure that removing a user 
# also removes the user's mail spool file.
# See comments in /etc/login.defs
session    optional   pam_mail.so standard

# Create a new session keyring.
session    optional   pam_keyinit.so force revoke

# Standard Un*x account and session
@include common-account
@include common-session
@include common-password

如果我用类似这样的脚本替换我的脚本:

#!/usr/bin/env python3
print('test')

motd 可以工作,但是当我尝试使用我的酷炫 motd 时,我没有得到任何输出。知道为什么会发生这种情况吗?我可以在哪里找到一些日志或其他东西来找出为什么没有输出?我正在使用 Ubuntu 18.10 Server

解决了

/etc/update-motd.d/00

#!/bin/zsh

export LANG='en_US.UTF-8'
/usr/bin/env python3 /etc/update-motd.d/00.py

相关内容