The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,835 other subscribers

Archive for the ‘ash/dash’ Category

Filezilla SFTP: figuring out the cause of “Connection timed out after 20 seconds of inactivity” part 2: about ((non-)?(interactive|login) ?){2} bash shells

Posted by jpluimers on 2022/05/12

Last year, I wrote about Filezilla: figuring out the cause of “Connection timed out after 20 seconds of inactivity” about sftp connection problems.

The solution there was to exclude part of bashrc with an if [Wayback] statement so bash would skip it during sftp, but not during ssh login:

[WayBack] linux – Use .bashrc without breaking sftp – Server Fault

  • From answer 1 (thanks [WayBack] Mike):

    Try doing this instead

    if [ "$SSH_TTY" ]
    then
       source .bashc_real
    fi
  • From Answer 2 (thanks [WayBack] Insyte):

    A good trick for testing the cleanliness of your login environment is to ssh in with a command, which simulates the same way scp/sftp connect. For example: ssh myhost /bin/true will show you exactly what scp/sftp sees when they connect.

That caused some scripts not to be run when switching user, for instance by doing sudo su -.

The reason for that was that I forgot to put enough research in part of Answer 2, so I quote a few bits more of it (highlights and code markup mine):

… it’s worth pointing out that you can accomplish this carefully selecting which startup files to put the verbose stuff in. From the bash man page:

When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. The --noprofile option may be used when the shell is started to inhibit this behavior.

When an interactive shell that is not a login shell is started, bash reads and executes commands from ~/.bashrc, if that file exists. This may be inhibited by using the --norc option. The --rcfile file option will force bash to read and execute commands from file instead of ~/.bashrc.

The sftp/scp tools start an interactive non-login shell, so .bashrc will be sourced.

For further reading, there is the underlying bash manual as a PDF file [Wayback] and html document tree [Wayback]. Note it is large (the PDF is 190 pages).

I find the easiest way to navigate around bash documentation through these links:

Types of shell invocations: to login or to non-login and to interactive or to non-interactive

Basically, from the above answer there are [Archive.is] 4 types of shells (confirmed by these parts of the bash documentation: [Wayback] Section 6.1: Invoking-Bash and [Wayback] Section 6.2: Bash-Startup-Files):

  1. interactive login
  2. interactive non-login
  3. non-interactive login
  4. non-interactive non-login

And there are various means the shells can start (ssh, local console, …). The "$SSH_TTY" trick only checks interactive login via ssh, but fails to detect others.

So I did some digging for the correct information to log, which including the above are:

  • [Wayback] Section 4.3.1: The-Set-Builtin
    • -h Locate and remember (hash) commands as they are looked up for execution. This option is enabled by default.
    • -m Job control is enabled (see Job Control). All processes run in a separate process group. When a background job completes, the shell prints a line containing its exit status.
    • -B The shell will perform brace expansion (see Brace Expansion). This option is on by default.
    • -H Enable ‘!’ style history substitution (see History Interaction). This option is on by default for interactive shells.

    Note that in addition to this, there is the non-settable option i: The current shell is interactive (see the -i in section 6.1 below).

  • [Wayback] Section 4.3.2: The-Shopt-Builtin
    • login_shell The shell sets this option if it is started as a login shell (see Invoking Bash). The value may not be changed.
  • [Wayback] Section 6.1: Invoking-Bash

    There are several single-character options that may be supplied at invocation which are not available with the set builtin.

    • -i Force the shell to run interactively. Interactive shells are described in Interactive Shells.

    login shell is one whose first character of argument zero is ‘-’, or one invoked with the –login option.

  • [Wayback] Section 6.2: Bash-Startup-Files explains about these shell invocation types:
    • interactive login shell
    • interactive non-login shell
    • non-interactive shell
  • [Wayback] Section 6.3.1: Is-this-Shell-Interactive

    To determine within a startup script whether or not Bash is running interactively, test the value of the ‘-’ special parameter. It contains i when the shell is interactive. For example:

    case "$-" in
    *i*)    echo This shell is interactive ;;
    *)  echo This shell is not interactive ;;
    esac
    

    Alternatively, startup scripts may examine the variable PS1; it is unset in non-interactive shells, and set in interactive shells. Thus:

    if [ -z "$PS1" ]; then
            echo This shell is not interactive
    else
            echo This shell is interactive
    fi

From theory to practice

After reading the above documentation links, I put the below code in the global .bashrc (which of course caused trouble with sftp, so I commented it out later):

echo "Option flags: '$-'"
echo "PS1: '$PS1'"
echo "shopt login_shell: '$(shopt login_shell)'"
echo "Parameter zero: '$0'"
[ "$SSH_TTY" ] ; echo "[ \"\$SSH_TTY\" ] outcome: $?"

And the output after these commands:

  1. ssh user@host
    Option flags: 'himBH'
    PS1: '\u@\h:\w> '
    shopt login_shell: 'login_shell     on'
    Parameter zero: '-bash'
    [ "$SSH_TTY" ] outcome: 0

    Verdict: interactive, login

  2. ssh user@host

    followed by

    sudo su -
    Option flags: 'himBH'
    PS1: '\[\]\h:\w #\[\] '
    shopt login_shell: 'login_shell     on'
    Parameter zero: '-bash'
    [ "$SSH_TTY" ] outcome: 1

    Verdict: interactive, login

  3. ssh user@host

    followed by

    bash
    Option flags: 'himBH'
    PS1: '\u@\h:\w> '
    shopt login_shell: 'login_shell     off'
    Parameter zero: 'bash'
    [ "$SSH_TTY" ] outcome: 0

    Verdict: interactive, non-login

  4. ssh user@host

    followed by

    sudo su -

    then by

    bash
    Option flags: 'himBH'
    PS1: '\[\]\h:\w #\[\] '
    shopt login_shell: 'login_shell     off'
    Parameter zero: 'bash'
    [ "$SSH_TTY" ] outcome: 1

    Verdict: interactive, non-login

  5. ssh user@host /bin/true
    Option flags: 'hBc'
    PS1: ''
    shopt login_shell: 'login_shell     off'
    Parameter zero: 'bash'
    [ "$SSH_TTY" ] outcome: 1

    Verdict: non-interactive, non-login

The final one is what for instance sftp will see. It excludes the non-interactive mark in the shopt option flags.

Modifications to my .bashrc file

Since the [Wayback] test for "$SSH_TTY" is inconsistent with the login being interactive, I modified the .bashrc section

if [ "$SSH_TTY" ]
then
   source .bashc_real
fi

to become

if [[ $- =~ i ]]
then
   # only during interactive login shells
   source .bashc_real
fi

I know the [[...]] over test shorthand [...] is a bashism, see [Wayback] if statement – Is double square brackets [[ ]] preferable over single square brackets [ ] in Bash? – Stack Overflow for why I like it.

More relevant documentation

I based the above changes not only on the mentioned StackOverflow post, but also doing some more Googling revealing these useful documentation and question/answer links:

  • [Wayback] Section 3.2.5.2: Conditional Constructs; [[ expression ]]

    [[…]]

    [[ expression ]]
    

    Return a status of 0 or 1 depending on the evaluation of the conditional expression expression. Expressions are composed of the primaries described below in Bash Conditional Expressions. Word splitting and filename expansion are not performed on the words between the [[ and ]]; tilde expansion, parameter and variable expansion, arithmetic expansion, command substitution, process substitution, and quote removal are performed. Conditional operators such as ‘-f’ must be unquoted to be recognized as primaries.

    An additional binary operator, ‘=~’, is available, with the same precedence as ‘==’ and ‘!=’. When it is used, the string to the right of the operator is considered a POSIX extended regular expression and matched accordingly (using the POSIX regcomp and regexec interfaces usually described in regex(3)). The return value is 0 if the string matches the pattern, and 1 otherwise. If the regular expression is syntactically incorrect, the conditional expression’s return value is 2.

  • [Wayback] Section 4.1: Bourne Shell Builtins; test or [...] (Bash Reference Manual)
    test expr
    

    Evaluate a conditional expression expr and return a status of 0 (true) or 1 (false). Each operator and operand must be a separate argument. Expressions are composed of the primaries described below in Bash Conditional Expressionstest does not accept any options, nor does it accept and ignore an argument of -- as signifying the end of options.

    When the [ form is used, the last argument to the command must be a ].

  • [Wayback] bash – What are the special dollar sign shell variables? – Stack Overflow (thanks [Wayback] kojiro!):
    • $1$2$3, … are the positional parameters.
    • "$@" is an array-like construct of all positional parameters, {$1, $2, $3 ...}.
    • "$*" is the IFS expansion of all positional parameters, $1 $2 $3 ....
    • $# is the number of positional parameters.
    • $- current options set for the shell.
    • $$ pid of the current shell (not subshell).
    • $_ most recent parameter (or the abs path of the command to start the current shell immediately after startup).
    • $IFS is the (input) field separator.
    • $? is the most recent foreground pipeline exit status.
    • $! is the PID of the most recent background command.
    • $0 is the name of the shell or shell script.

    Most of the above can be found under Special Parameters in the Bash Reference Manual. There are all the environment variables set by the shell.

    For a comprehensive index, please see the Reference Manual Variable Index.

  • [Wayback] bash – Differentiate Interactive login and non-interactive non-login shell – Ask Ubuntu (thanks [Wayback] terdon)

    Briefly (see here for more details), with examples:

    • interactive login shell: You log into a remote computer via, for example ssh. Alternatively, you drop to a tty on your local machine (Ctrl+Alt+F1) and log in there.
    • interactive non-login shell: Open a new terminal.
    • non-interactive non-login shell: Run a script. All scripts run in their own subshell and this shell is not interactive. It only opens to execute the script and closes immediately once the script is finished.
    • non-interactive login shell: This is extremely rare, and you’re unlikey to encounter it. One way of launching one is echo command | ssh server. When ssh is launched without a command (so ssh instead of ssh command which will run command on the remote shell) it starts a login shell. If the stdin of the ssh is not a tty, it starts a non-interactive shell. This is why echo command | ssh server will launch a non-interactive login shell. You can also start one with bash -l -c command.

    If you want to play around with this, you can test for the various types of shell as follows:

    • Is this shell interactive?Check the contents of the $- variable. For interactive shells, it will include i:
      ## Normal shell, just running a command in a terminal: interacive
      $ echo $-
      himBHs
      ## Non interactive shell
      $ bash -c 'echo $-'
      hBc
      
    • Is this a login shell?There is no portable way of checking this but, for bash, you can check if the login_shell option is set:
      ## Normal shell, just running a command in a terminal: interacive
      $ shopt login_shell 
      login_shell     off
      ## Login shell; 
      $ ssh localhost
      $ shopt login_shell 
      login_shell     on
      

    Putting all this together, here’s one of each possible type of shell:

    ## Interactive, non-login shell. Regular terminal
    $ echo $-; shopt login_shell
    himBHs
    login_shell     off
    
    ## Interactive login shell
    $ bash -l
    $ echo $-; shopt login_shell
    himBHs
    login_shell     on
    
    ## Non-interactive, non-login shell
    $ bash -c 'echo $-; shopt login_shell'
    hBc
    login_shell     off
    
    ## Non-interactive login shell
    $ echo 'echo $-; shopt login_shell' | ssh localhost
    Pseudo-terminal will not be allocated because stdin is not a terminal.
    hBs
    login_shell     on
  • [Wayback] Difference between Login Shell and Non-Login Shell? – Unix & Linux Stack Exchange

    A login shell is the first process that executes under your user ID when you log in for an interactive session. The login process tells the shell to behave as a login shell with a convention: passing argument 0, which is normally the name of the shell executable, with a - character prepended (e.g. -bash whereas it would normally be bash. Login shells typically read a file that does things like setting environment variables: /etc/profile and ~/.profile for the traditional Bourne shell, ~/.bash_profile additionally for bash/etc/zprofile and ~/.zprofile for zsh/etc/csh.login and ~/.login for csh, etc.

    When you log in on a text console, or through SSH, or with su -, you get an interactive login shell. When you log in in graphical mode (on an X display manager), you don’t get a login shell, instead you get a session manager or a window manager.

    It’s rare to run a non-interactive login shell, but some X settings do that when you log in with a display manager, so as to arrange to read the profile files. Other settings (this depends on the distribution and on the display manager) read /etc/profile and ~/.profile explicitly, or don’t read them. Another way to get a non-interactive login shell is to log in remotely with a command passed through standard input which is not a terminal, e.g. ssh example.com <my-script-which-is-stored-locally (as opposed to ssh example.com my-script-which-is-on-the-remote-machine, which runs a non-interactive, non-login shell).

    When you start a shell in a terminal in an existing session (screen, X terminal, Emacs terminal buffer, a shell inside another, etc.), you get an interactive, non-login shell. That shell might read a shell configuration file (~/.bashrc for bash invoked as bash/etc/zshrc and ~/.zshrc for zsh, /etc/csh.cshrc and ~/.cshrc for csh, the file indicated by the ENV variable for POSIX/XSI-compliant shells such as dash, ksh, and bash when invoked as sh$ENV if set and ~/.mkshrc for mksh, etc.).

    When a shell runs a script or a command passed on its command line, it’s a non-interactive, non-login shell. Such shells run all the time: it’s very common that when a program calls another program, it really runs a tiny script in a shell to invoke that other program. Some shells read a startup file in this case (bash runs the file indicated by the BASH_ENV variable, zsh runs /etc/zshenv and ~/.zshenv), but this is risky: the shell can be invoked in all sorts of contexts, and there’s hardly anything you can do that might not break something.

     I’m simplifying a little, see the manual for the gory details.

If you want to avoid the [[...]] bashishm, then read [Wayback] Bashism: How to make bash scripts work in dash – Greg’s Wiki.

–jeroen

Posted in *nix, *nix-tools, ash/dash, bash, bash, Communications Development, Conference Topics, Conferences, Development, Event, Internet protocol suite, Power User, Scripting, SFTP, Software Development, SSH, TCP | Leave a Comment »

Kris on Twitter is a bit radical against shell scripts. Learn why.

Posted by jpluimers on 2022/04/13

I say to people: only use shell interactively, don’t write scripts. Never. Not one.
But Kris, they ask, why so radical?
Because of this:

is the literal English Google Translation of the German text

Ich sage den Leuten: benutzt Shell nur interaktiv, schreibt keine Scripte. Nie. Nicht eines.
Aber Kris, fragen sie, wieso so Radikal?
Deswegen:

then links to [Wayback/Archive] Jan Schaumann on Twitter: “TIL zgrep(1) is a shell script. BSD basically does “zcat | grep”, but GNU does “gzip -dc | sed”. How did I learn that? The fun way! CVE-2022-1271, arbitrary-file-write and code execution vulnerability in GNU zgrep / gzip. …”:

Read the rest of this entry »

Posted in *nix, *nix-tools, Apple, ash/dash, ash/dash development, bash, bash, BSD, Development, Mac, Mac OS X / OS X / MacOS, Power User, Scripting, Software Development | Leave a Comment »

When some virtual machines cannot run VMware Tools: Graceful shutdown of an ESXi 5.1 host and guest VMs (free edition) using the shell/command line/scripting (UPS friendly)

Posted by jpluimers on 2022/04/12

An interesting set of scripts from [Wayback/Archive.is] No Joke IT: Graceful shutdown of an ESXi 5.1 host and guest VMs (free edition) using the shell/command line/scripting (UPS friendly).

If all ESXi virtual machines support running of VMware Tools, then the solution is a plain /sbin/shutdown.sh && /sbin/poweroff (see [Wayback/Archive.is] No Joke IT: Shut down ESXi 5.1 guest VMs and the host (free edition) via SSH – the easy way!).

Code is in the repository at [Wayback/Archive.is] sixdimensionalarray/esxidown: A shell script to shutdown VMware ESXi host servers, with these two main files:

Note: the No Joke IT web-site has vanished, so only the [Wayback] and [Archive.is] links of it still work. The github code was still there at the time of writing.

Via: [Wayback] Solved: Read only Files – VMware Technology Network VMTN

Related: Some notes on replacing parts of a text file with template text using sed on a Busybox system.

–jeroen

Posted in *nix, *nix-tools, ash/dash, ash/dash development, Development, ESXi5, ESXi5.1, ESXi5.5, ESXi6, ESXi6.5, ESXi6.7, Power User, Scripting, Software Development, Virtualization, VMware, VMware ESXi | Leave a Comment »

Some notes on replacing parts of a text file with template text using sed on a Busybox system

Posted by jpluimers on 2022/03/17

Note before you think about putting stuff in /etc/rc.local.d/local.sh: that script will not be executed when UEFI booting.

In a very lightweight Busybox system, I wanted to modify some configuration files automatically using fragments stored in template files.

The system has diff, but no patch.

The basic idea is to use sed to insert the template files into certain spots of the configuration file when certain marker texts are not present. So I want the opposite of [Wayback] Hey Stephen Wood: Try patch instead of sed in shell scripts.

Basically the idea is a poor-man’s patch, described in Too bad: ESXi busybox has diff, but not patch « The Wiert Corner – irregular stream of stuff.

Some links that might help me with this:

One alternative would have been to use ed (which is part of the normal Busybox), but ESXi Busybox omits ed like it omits patch.

Too bad that sed commands are too different from ed commands, as I could have used diff -e on another system based on ideas here:

I might give it one more go, as vi is sort of derived from ed via ex (see vi: Creation – Wikipedia), which means that vi “colon mode” (officially command mode: [Wayback] Vim documentation: cmdline) is very similar to ed.

Another alternative would be awk, but I have done so little work with it awk, that I’m hesitating to use a new tool. Some links:

And finally, ash could be used:

The kind of modifications I am after

Below are a few links with examples of the kind of modifications I want to make. Most patch just /etc/rc.local.d/local.sh, but some others introduce other changes as well.

Note that especially with networking settings, local.sh commands might not have any effect (for instance when having slow DHCP or other network issues), see for instance [Wayback/Archive.is] I’m running ESXi 5.5 and my persistent route in local.sh is not taking effect after boot. : vmware.

There is a very convoluted way around using local.sh by using the VIB authoring tool as described in [Wayback] How to create persistent firewall rules on ESXi. It requires lowering the software acceptance level to Community Supported (esxcli software acceptance set --level=CommunitySupported), which gives you a hard time installing ESXi updates.

I got that VIB idea from [Wayback] Solved: Re: Persistent firewall rule – VMware Technology Network VMTN, as:

The local.sh file gets overwritten often with upgrades so it would mean another step during the process.

From the same thread comes [Wayback] Solved: Re: Persistent firewall rule – VMware Technology Network VMTN

set the sticky bit on your separate xml-file – then it will be backed up and persist through reboot: chmod +t

run backup manually before the first reboot: /sbin/auto-backup.sh  because backup runs only once per hour

Within vSphere, one could use [Wayback] Configure ESXi Hosts with Host Profiles, but a standalone ESXi box is not part of vSphere, so that won’t work.

ESXi 7 and up

ESXi 7 makes the above harder as for instance user root cannot change file rights any more, so eventually I might revert to a VM that auto-boots when ESXi comes up, then patches the right files in place over PowerCLI (read-only) or SSH.

Need to give this some thought later:

–jeroen

Posted in *nix, *nix-tools, ash/dash, ash/dash development, Awk, BusyBox, Development, ESXi6, ESXi6.5, ESXi6.7, ESXi7, Power User, PowerCLI, Scripting, sed, sed script, Software Development, Virtualization, VMware, VMware ESXi | Leave a Comment »

Some insights on how readlink approached canonicalisation of a filename having symlinks

Posted by jpluimers on 2022/03/03

Cool, I didn’t realise how readlink operated, but found out a bit more in the answers to [Wayback] symlink – How to get full path of original file of a soft symbolic link? – Unix & Linux Stack Exchange, thanks to [Wayback] daisy, [Wayback] Peter.O and [Wayback] Gilles ‘SO- stop being evil’:

  • Try this line:
    readlink -f `which command`
    

    If command is in your $PATH variable , otherwise you need to specify the path you know.

    -f will return a path to a non-existent final target, so long as the intermediate link targets exist… Use -e to avoid this, ie. -e will return null if the final target does not exist. – Peter.O

  • Under Linux, readlink reads the contents of a symlink, and readlink -f follows symlinks to symlinks to symlinks, etc., until it finds something that isn’t a symlink.

–jeroen

Posted in *nix, *nix-tools, ash/dash, bash, bash, Development, Power User, Scripting, Software Development | Leave a Comment »

Too bad: ESXi busybox has `diff`, but not `patch`

Posted by jpluimers on 2022/03/02

On my ESXi boxes, I have a directory with local scripts that in part depend on the machine.

So I contemplated patching the dending parts with patch.

Then I found out that the BusyBox that VMware built for ESXi does have diff, but not patch:

# $(readlink -f "`which diff`")
BusyBox v1.29.3 (2021-01-17 01:25:00 PST) multi-call binary.
BusyBox is copyrighted by many authors between 1998-2015.
Licensed under GPLv2. See source distribution for detailed
copyright notices.

Usage: busybox [function [arguments]...]
   or: busybox --list
   or: function [arguments]...

    BusyBox is a multi-call binary that combines many common Unix
    utilities into a single executable.  Most people will create a
    link to busybox for each function they wish to use and BusyBox
    will act like whatever it was invoked as.

Currently defined functions:
    addgroup, adduser, arch, ash, awk, basename, bunzip2, bzcat, bzip2, cat, chgrp, chmod, chown, chvt, cksum, clear, cp, crond,
    cut, date, dd, delgroup, deluser, diff, dirname, dnsdomainname, du, echo, egrep, eject, env, expr, false, fdisk, fgrep, find,
    fstrim, getty, grep, groups, gunzip, gzip, halt, head, hexdump, hostname, inetd, init, kill, ln, logger, login, ls, lzop,
    lzopcat, md5sum, mkdir, mkfifo, mknod, mktemp, more, mv, nohup, nslookup, od, passwd, poweroff, printf, readlink, reboot,
    reset, resize, rm, rmdir, sed, seq, setsid, sh, sha1sum, sha256sum, sha3sum, sha512sum, sleep, sort, ssl_client, stat, stty,
    sum, sync, tail, tar, taskset, tee, test, time, timeout, touch, true, uname, uniq, unlink, unlzop, unzip, usleep, vi, watch,
    wc, wget, which, who, xargs, zcat

This list is much shorter than the applets that are supported in [Wayback] BusyBox – The Swiss Army Knife of Embedded Linux, so VMware did cut out quite a few.

Generating the above output

The command-line trick above first expands diff using the output of which diff, then finds out where it links to through the readlink -f wrapper there the back-quotes “`” get this output:

# readlink -f "`which diff`"
/usr/lib/vmware/busybox/bin/busybox

Finally the $(...) executes the output of readlink.

It is based on [Wayback] bash – How to resolve symbolic links in a shell script – Stack Overflow

readlink -f "$path"

Editor’s note: The above works with GNU readlink and FreeBSD/PC-BSD/OpenBSD readlink, but not on OS X as of 10.11.GNU readlink offers additional, related options…

Need to devise a way to apply patches

Given there is no patch, I need to think about a good way to apply patches, for instance to snip this into /etc/rc.local.d/local.sh in a reliable way:

## BEGIN-PATCH-PATH

# local binaries are in /vmfs/volumes/NVMe980PRO_1TB/local-bin/
# link that directory from /opt/bin
# then add /opt/bin to the PATH in /etc/profile so that on each logon it becomes available
# this means you need to logon twice after reboot:
# - first to patch /etc/profile
# - second to have the correct PATH loaded from /etc/profile
# direcory exist trick from https://stackoverflow.com/questions/59838/how-can-i-check-if-a-directory-exists-in-a-bash-shell-script

patch_etc_profile_PATH() {
    if [ -d "$1" ]; then
      ln -s "$1" "/opt/bin"
      sed -i -e 's!PATH=/bin:/sbin!PATH=/bin:/sbin:/opt/bin/!' /etc/profile
    fi
}

patch_etc_profile_PATH /vmfs/volumes/NVMe980PRO_1TB/local-bin/

## END-PATCH-PATH

–jeroen

Posted in *nix, *nix-tools, ash/dash, ash/dash development, BusyBox, Development, ESXi6, ESXi6.5, ESXi6.7, ESXi7, Power User, Scripting, Software Development, Virtualization, VMware, VMware ESXi | Leave a Comment »

ESXi: on the console/ssh, when a moved VM pauses during power-on: show which VMs have messages waiting, then answer them

Posted by jpluimers on 2022/01/27

First the script that display messages for all virtual machines, vim-cmd-display-messages-for-all-VMs.sh:

#!/bin/sh
vmids=`vim-cmd vmsvc/getallvms | sed -n -E -e "s/^([[:digit:]]+)\s+((\S.+\S)?)\s+(\[\S+\])\s+(.+\.vmx)\s+(\S+)\s+(vmx-[[:digit:]]+)\s*?((\S.+)?)$/\1/p"`
for vmid in ${vmids} ; do
    powerState=`vim-cmd vmsvc/power.getstate ${vmid} | sed '1d'`
    name=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/\(vim.vm.ConfigInfo\) \{/,/files = \(vim.vm.FileInfo\) \{/ s/^ +name = "(.*)",.*?/\1/p'`
    vmPathName=`vim-cmd vmsvc/get.config ${vmid} | sed -n -E -e '/files = \(vim.vm.FileInfo\) \{/,/tools = \(vim.vm.ToolsConfigInfo\) \{/ s/^ +vmPathName = "(.*)",.*?/\1/p'`
    echo "Messages for VM with id ${vmid} which has power state ${powerState} (name = ${name}; vmPathName = ${vmPathName})."
    vim-cmd vmsvc/message ${vmid}
done
exit 0

It is very similar to vim-cmd-reload-all-VM-vmx-configurations.sh from Source: ESXi: reloading all virtual machines from their (potentially) vmx files.

Messages I know either equal “No message” or are about “This virtual machine may have been moved or copied.

If there is no available message, then you always get the stock message No message., so this is something you can use as a check in scripts.

Read the rest of this entry »

Posted in *nix, *nix-tools, ArchiveTeamWarrior, ash/dash, ash/dash development, Development, ESXi6, ESXi6.5, ESXi6.7, ESXi7, Power User, Scripting, Software Development, Virtualization, VMware, VMware ESXi | Leave a Comment »

ESXi: storing an ISO 8601 time-stamped backup tarball locally

Posted by jpluimers on 2022/01/25

In Determining the ESXi installation type (2014558) | VMware KB, I also showed how to backup the configuration and download it.

Sometimes you want an ISO 8601 time-stamped local tarball just in case you want to revert to it at a later stage.

First a small recap on how to get the tarball, download location and temporary location in the first place (it will be automatically deleted from the temporary location):

# vim-cmd hostsvc/firmware/sync_config
# vim-cmd hostsvc/firmware/backup_config
Bundle can be downloaded at : http://*/downloads/52aa233b-5db4-2298-5e1b-f510b2cd149f/configBundle-ESXi-X10SRH-CF.tgz
# find /scratch/downloads/ -name *.tgz
/scratch/downloads/52aa233b-5db4-2298-5e1b-f510b2cd149f/configBundle-ESXi-X10SRH-CF.tgz

Goal is to get the download filename and save it to a different folder and embed the ISO 8601 timestamp in the filename.

Like many scripts, sed and regular expressions come to the rescue once more, just like in ESXi ash/dash/busybox shell getting current timestamp in UTC ISO8601 format without colons or dashes (which we will need anyway because of the ISO 8601 time stamp, and a bit of fiddling at regex101.com/r/NyrzKF

# SCRATCH_CONFIG_BUNDLE_NAME=$(vim-cmd hostsvc/firmware/backup_config | sed -n -E -e "s/^(Bundle can be downloaded at : http://*)(/downloads/[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}/configBundle-.+?)(.tgz)$//scratch23/p")
# echo "SCRATCH_CONFIG_BUNDLE_NAME: '${SCRATCH_CONFIG_BUNDLE_NAME}'"
SCRATCH_CONFIG_BUNDLE_NAME: '/scratch/downloads/5271677d-97db-30dc-673d-b99e61bed251/configBundle-ESXi-X10SRH-CF.tgz'
# date --utc -I'seconds' --reference "${SCRATCH_CONFIG_BUNDLE_NAME}"
2021-05-09T17:44:42UTC

Note:

  • In the sed regular, expression, [[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12} matches a GUID.
  • In the date command, the --reference parameter must be last.
  • If you get the error below, then you ran too many backup_config commands in succession:
    (vim.fault.TooManyWrites) {
       faultCause = (vmodl.MethodFault) null, 
       faultMessage = 
       msg = "Received SOAP response fault from []: syncConfiguration
    fault.TooManyWrites.summary"
    }

    You can see this in the hostd.log, which on my system is in /scratch/log/hostd.log where it says I can retry in 2031 seconds (slightly more than half an hour):

    2021-05-09T19:34:13.420Z verbose hostd[A703B70] [Originator@6876 sub=PropertyProvider opID=vim-cmd-27-2ab3] RecordOp ASSIGN: latestEvent, ha-eventmgr. Applied change to temp map.
    2021-05-09T19:34:13.420Z info hostd[A703B70] [Originator@6876 sub=Vimsvc.ha-eventmgr opID=vim-cmd-27-2ab3] Event 196 : User root@127.0.0.1 logged in as VMware-client/6.5.0
    2021-05-09T19:34:13.420Z verbose hostd[A703B70] [Originator@6876 sub=PropertyProvider opID=vim-cmd-27-2ab3] RecordOp ADD: sessionList["52f6d64e-0a35-c1d7-de97-624d234bc2a7"], ha-sessionmgr. Applied change to temp map.
    2021-05-09T19:34:13.423Z info hostd[9AC1B70] [Originator@6876 sub=Vimsvc.TaskManager opID=vim-cmd-27-2ab5 user=root] Task Created : haTask--vim.host.FirmwareSystem.syncConfiguration-114207804
    2021-05-09T19:34:13.423Z verbose hostd[9AC1B70] [Originator@6876 sub=PropertyProvider opID=vim-cmd-27-2ab5 user=root] RecordOp ADD: recentTask["haTask--vim.host.FirmwareSystem.syncConfiguration-114207804"], ha-taskmgr. Applied change to temp map.
    2021-05-09T19:34:13.423Z verbose hostd[9AC1B70] [Originator@6876 sub=PropertyProvider opID=vim-cmd-27-2ab5 user=root] RecordOp ASSIGN: info, haTask--vim.host.FirmwareSystem.syncConfiguration-114207804. Applied change to temp map.
    2021-05-09T19:34:13.423Z error hostd[9AC1B70] [Originator@6876 sub=Hostsvc.FirmwareSystem opID=vim-cmd-27-2ab5 user=root] Failed to sync configuration. Too many writes. Next sync possible in 2031 sec.
    2021-05-09T19:34:13.423Z info hostd[9AC1B70] [Originator@6876 sub=Default opID=vim-cmd-27-2ab5 user=root] AdapterServer caught exception: vim.fault.TooManyWrites
    2021-05-09T19:34:13.423Z info hostd[9AC1B70] [Originator@6876 sub=Vimsvc.TaskManager opID=vim-cmd-27-2ab5 user=root] Task Completed : haTask--vim.host.FirmwareSystem.syncConfiguration-114207804 Status error
    2021-05-09T19:34:13.423Z verbose hostd[9AC1B70] [Originator@6876 sub=PropertyProvider opID=vim-cmd-27-2ab5 user=root] RecordOp ASSIGN: info, haTask--vim.host.FirmwareSystem.syncConfiguration-114207804. Applied change to temp map.
    2021-05-09T19:34:13.423Z info hostd[9AC1B70] [Originator@6876 sub=Solo.Vmomi opID=vim-cmd-27-2ab5 user=root] Activation [N5Vmomi10ActivationE:0x0987e6e0] : Invoke done [syncConfiguration] on [vim.host.FirmwareSystem:ha-firmwareSystem]
    2021-05-09T19:34:13.423Z info hostd[9AC1B70] [Originator@6876 sub=Solo.Vmomi opID=vim-cmd-27-2ab5 user=root] Throw vim.fault.TooManyWrites
    2021-05-09T19:34:13.423Z info hostd[9AC1B70] [Originator@6876 sub=Solo.Vmomi opID=vim-cmd-27-2ab5 user=root] Result:
    --> (vim.fault.TooManyWrites) {
    -->    faultCause = (vmodl.MethodFault) null,
    -->    faultMessage = 
    -->    msg = ""
    --> }
    

Not few people have bumped into this, the only other I could find through [Wayback] “vim.fault.TooManyWrites” “syncConfiguration” – Google Search is [Archive.is] mal wieder purple Screen – VMware-Forum.

Figuring out the various parts of the SCRATCH_CONFIG_BUNDLE_NAME: '/scratch/downloads/5271677d-97db-30dc-673d-b99e61bed251/configBundle-ESXi-X10SRH-CF.tgz' is like at regex101.com/r/J4yU72, regex101.com/r/uID9xs and regex101.com/r/o8a4Am:

CONFIG_BUNDLE_DIRECTORY_NAME=$(echo "${SCRATCH_CONFIG_BUNDLE_NAME}" | sed -n -E -e "s/(\/scratch\/downloads\/[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}\/)(configBundle-.+?)(.tgz)$/\1/p")
CONFIG_BUNDLE_FILE_NAME=$(     echo "${SCRATCH_CONFIG_BUNDLE_NAME}" | sed -n -E -e "s/(\/scratch\/downloads\/[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}\/)(configBundle-.+?)(.tgz)$/\2/p")
CONFIG_BUNDLE_DOT_EXTENSION=$( echo "${SCRATCH_CONFIG_BUNDLE_NAME}" | sed -n -E -e "s/(\/scratch\/downloads\/[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}\/)(configBundle-.+?)(.tgz)$/\3/p")
echo "CONFIG_BUNDLE_DIRECTORY_NAME: '${CONFIG_BUNDLE_DIRECTORY_NAME}'"
echo "CONFIG_BUNDLE_FILE_NAME:      '${CONFIG_BUNDLE_FILE_NAME}'"
echo "CONFIG_BUNDLE_DOT_EXTENSION:  '${CONFIG_BUNDLE_DOT_EXTENSION}'"

Output is like this:

SCRATCH_CONFIG_BUNDLE_NAME:   '/scratch/downloads/528f9f5a-0123-f022-2b4d-a5c2e595c51a/configBundle-ESXi-X10SRH-CF.tgz'
CONFIG_BUNDLE_DIRECTORY_NAME: '/scratch/downloads/528f9f5a-0123-f022-2b4d-a5c2e595c51a/'
CONFIG_BUNDLE_FILE_NAME:      'configBundle-ESXi-X10SRH-CF'
CONFIG_BUNDLE_DOT_EXTENSION:  '.tgz'

Full backup-config-to-ESXi_configuration_backup-directory.sh script:

Read the rest of this entry »

Posted in *nix, *nix-tools, ash/dash, ash/dash development, cron/crontab, Development, ESXi6, ESXi6.5, ESXi6.7, ESXi7, Power User, Scripting, Software Development, Virtualization, VMware, VMware ESXi | Leave a Comment »

ESXi: getting and setting the host name, domain and fqdn

Posted by jpluimers on 2022/01/19

A few links and notes:

  1. [Wayback] Changing the hostname of an ESX or ESXi host (1010821)

    Run these commands to change the hostname in ESXi 5.x, ESXi 6.x,ESXi 7.x, using the command line:

    • esxcli system hostname set –host=hostname
    • esxcli system hostname set –fqdn=fqdn
  2. [Wayback] ESX Host appears as localhost.localdomain in VMware Infrastructure/vSphere client (2009720)

    Cause

    The name resolution parameters were not properly configured during the installation of the ESX host.
  3. [Wayback] Domain repoint for embedded vCenter Server fails with error: “domain_consolidator Failed to set machine id” (71020)

    This issue is caused by a mismatch between the FQDN that was configured as the PNID during the vCenter Server deployment and the hostname that is currently configured.

I had a mismatch happen because of the second entry: a host configured in a different domain than it was deployed to.

Here are the commands to list and change the hosts name, domain and fqdn:

Read the rest of this entry »

Posted in *nix, *nix-tools, ash/dash, ash/dash development, Development, ESXi6, ESXi6.5, ESXi6.7, ESXi7, Power User, Scripting, Software Development, Virtualization, VMware, VMware ESXi | Leave a Comment »

ESXi: persistent files you can edit to apply settings during boot

Posted by jpluimers on 2022/01/18

Since ESXi boots from RAM, most files in /etc are not persisted after modification.

The files that are persisted, are only persisted once every hour by auto-backup.sh, so better run auto-backup.sh by hand if you want to reboot after changing them.

The auto-backup.sh script is ran every hour at 1 minute past the hour as per below crontab.

Default ESXi crontab in /var/spool/cron/crontabs/root:

#min hour day mon dow command
1    1    *   *   *   /sbin/tmpwatch.py
1    *    *   *   *   /sbin/auto-backup.sh
0    *    *   *   *   /usr/lib/vmware/vmksummary/log-heartbeat.py
*/5  *    *   *   *   /bin/hostd-probe.sh ++group=host/vim/vmvisor/hostd-probe/stats/sh
00   1    *   *   *   localcli storage core device purge

Schedules deciphered via [Wayback] Crontab.guru – The cron schedule expression editor:

  • [Wayback] Every day at 01:01: “This module removes stale temporary files”
    1    1    *   *   *   /sbin/tmpwatch.py
  • [Wayback] Every hour at *:01: saves backup to /bootbank/state.tgz.
    1    *    *   *   *   /sbin/auto-backup.sh
  • [Wayback] Every hour at *:00 logs heartbeat messages to /var/log/vmksummary.log like 2021-02-23T19:00:02Z heartbeat: up 577d2h37m16s, 9 VMs; [[2802426 vmx 4194304kB] [6176344 vmx 4194304kB] [68997 vmx 8388608kB]] [[2802426 vmx 0%max] [6176344 vmx 0%max] [68997 vmx 0%max]]
    0    *    *   *   *   /usr/lib/vmware/vmksummary/log-heartbeat.py
  • [Wayback] Every 5th minute logs to /var/log/hostd-probe.log.
    */5  *    *   *   *   /bin/hostd-probe.sh ++group=host/vim/vmvisor/hostd-probe/stats/sh
  • [Wayback] Every day at 01:00: Removes storage devices which have not been seen in some time interval.
    00   1    *   *   *   localcli storage core device purge

Note that localcli commands are the same as esxcli; for esxcli, a running hostd is required; localcli can run without hostd. See:

–jeroen

Posted in *nix, *nix-tools, ash/dash, ash/dash development, Development, ESXi6, ESXi6.5, ESXi6.7, ESXi7, Power User, Scripting, Software Development, Virtualization, VMware | Leave a Comment »