mac terminal computer name is garbled - bash

When I use terminal enter zsh, my computer name is garbled, n3-85-8 instead MacBook-Pro. Sometime so as the bash. Do anyone know why? And how to fix it.

There are two effects happening here:
Bash only reads the hostname (as displayed in the prompt) once at shell startup, which means you only see the change when you start a new shell, not when your hostname changes.
macOS by default changes its own hostname based on the network configuration
You can configure your computer not to change its hostname (see for example this question). Or, you can configure bash to use the computer's persistent LocalHostName in the prompt. This value does not change when you connect to a different network.
You can edit your ~/.bashrc (or related file) to have a line like:
PS1=$(scutil --get LocalHostName)':\W \u\$'

Extending Grisha's excellent answer, there are several different host names. Often the same, but may vary to accommodate different naming constraints. The whatami function (below) can help you choose which one you want in your PS1 prompt.
Here's a Bash function to help assess the different names.
function whatami {
local cn=$(scutil --get ComputerName)
local lhn=$(scutil --get LocalHostName)
local hn=$(scutil --get HostName)
local nbn=$(/usr/libexec/PlistBuddy -c "Print :NetBIOSName" /Library/Preferences/SystemConfiguration/com.apple.smb.server.plist)
printf '\e[1mComputerName\e[0m: '"$cn"'\n'
printf '\e[1mLocalHostName\e[0m (Bonjour): '"$lhn"'\n'
printf '\e[1mHostName\e[0m: '"$hn"'\n'
printf '\e[1mNetBIOSName\e[0m (SMB): '"$nbn"'\n'
printf '\e[1mIP Address\e[0m: '
for x in $(ifconfig -l); do ipconfig getifaddr $x; done
}

Related

How to use openssh-client in Cyberark environments with autocompletion and multiple servers?

I usually have what I need in my ~/.ssh/ folder (a config file and more) to connect to servers with ssh <tab><tab>. In an environment with Cyberark the configuration seems to be a bit more intricate due to the three # signs
I found this answer, but I struggled to find a way to enjoy autocompletion for many hosts because the User field does not support tokens like %h for host, so I'd have to create the same entry again for every server where I previously just added servers to the Host line. Is there a way this can be achieved?
After spending some time I came up with the following solution which is more like a workaround. I'm not really proud of it, but it gets the job done with the least amount of new code or difficult to understand code.
Create a wrapper script like this:
$ cat ~/bin/ssh-wrapper.sh
#!/bin/bash
# https://docs.cyberark.com/Product-Doc/OnlineHelp/PAS/latest/en/Content/PASIMP/PSSO-PMSP.htm#The
# Replace where appropriate:
# $1 = Server FQDN
# prefix = your administrative user may be different from you normal user
# internal.example.org = domain server (controller)
# pam.example.org = Cyberark jump host
ssh -t ${USERNAME,,}#prefix${USERNAME,,}#internal.example.org#$1#pam.example.org
Add the following to your bash startup file. Yours may be different than mine, because I'm hacking here in a customer environment with Tortoise Git-Bash. (Which works nice by the way when you use it with Flux Terminal, k9s and jq.)
Create an alias for you wrapper script, I chose sshw here.
Create variable with all the FQDNs of the servers you want to have in your autocompletion, or create file which contains these FQDNs and read it to a variable.
Create a bash completion expression which applies this to your sshw alias.
$ cat ~/.bash_profile
alias sshw="$HOME/bin/ssh-wrapper.sh"
SSH_COMPLETE=$(cat "$HOME/.ssh/known_hosts_wrapper")
complete -o default -W "${SSH_COMPLETE[*]}" sshw
Now you can tab you way to servers.

Argument list too long for UGE compute host

In my .profile (SUSE Linux with Korn shell) I have had the following code active for many years:-
case $0 in
-ksh|ksh)
set -o ignoreeof
set -a
set -o vi
PS1=$(print '\033[34m$(tput bold)ksh:$(hostname)->$(tput sgr0)\033[00m ')
PS2="continue-> "
PS3=": "
PS4="$0.$LINENO+ "
FCEDIT=/usr/bin/vi
HISTFILE=~/.histories/${TTY}_$(hostname)_ksh_his
HISTSIZE=500
EDITOR=/bin/vi
VISUAL=/bin/vi
TERM=gnome
set +a ;;
*) SHELL=${SHELL} ;;
But lately that PS1 entry has been causing some unexpected problems. When I source a file of ~3K environment variables and then try to get onto to a UGE compute host, the following error causes everything to break down:-
$ qrsh -V -j y -pe mt 1 -l "os_version=SUSE12.0,model=EMT3500,cpu_code=E5-2667v4" -P iheavy -now no
ksh: /usr/bin/tput: Argument list too long
ksh: /bin/hostname: Argument list too long
ksh: /usr/bin/tput: Argument list too long
ksh:->
If I request a CentOS system (os_version=CS7.0) I do not see the error--it is specific to SUSE. Also, if I eliminate the PS1 entry altogether, I can get onto a SUSE system without any errors. This is the simplest way to capture the bigger problem: when I issue a qsub for batch computing tasks, my .profile ends up partially initialized and jobs fail to launch.
I often change environments and shells, so color-coding my terminal prompt in a shell-specific and host/queue-specific way has always been helpful. I would rather not retire that PS1 entry just for one project that has such a long list of environment variable names.
I have done various searches and learned that increasing ulimit settings can sometimes help in situations like this; however, I tried that (increased stack size and number-of-open-files to their maximum) and the outcome did not change.
Is there a practical way to avoid this problem without removing the PS1 entry?

Unix side-by-side difference with a remote hidden file

I am working on a battery of automatic tests which executes on 2 Unix virtual machines running with KSH. Those VMs are independant and they have practically the same .profile file. I would like to study their differences by launching:
tkdiff /usr/system/.profile system#{external_IP}:/usr/system/.profile
on the first VM but it doesn't work.
I suppose that directly accessing a hidden file is not possible. Is there a solution to my problem, or maybe an alternative?
If you want to compare different files on two remote machines, I suggest the following procedure:
1. Compare checksums:
First compare the checksums. Use sum, md5sum or sha256sum to compute a hash of the file. If the hash is the same, the probability of having the same file is extremely high! You can even increase that probability by check the total amount of characters, lines and words, in the file using wc.
$ file="/usr/system/.profile"
$ md5sum "$file" && wc "$file"
$ ssh user#host "md5sum '$file' && wc '$file'"
2. run a simple diff
Run a simple diff using the classic command line tools. They understand the POSIX standard to use - as /dev/stdin. This way you can do:
$ ssh user#host "cat -- '$file'" | diff "$file" -
note: with old versions of tkdiff or new versions of svn/git, it can be tricky here due to bugs in tkdiff. It will quickly throw errors of the form svn [XXXX] file .... is not a working copy or file xxxx is not part of a revision control system if one of the files might be under version control or you end up in a directory under version control. Stick to diff!
You are using the filename convention "user#host:/path/to/file" for the second argument to tkdiff.
That convention for naming is not native to Ksh, but instead is understood by some programs like scp and others (which can be interactive, e.g. to ask for a password for the remote system or other authentication related questions).
But from the tkdiff man page, it does not mention having built-in support for that filenaming convention userid#host:/path/to/file, and neither is such support built into ksh.
So you may need to use two steps, first to use scp or similar to copy the remote file locally then then use tkdiff with one argument the local file and the other the file-just-copied, or arrange to mount part of the other VM filesystem locally, and then use tkdiff with appropriate arguments.
Obviously, both files need to be readable by your userid or the user specified on the userid#host:/path/to/file for this to work.
You can directly made a remote ssh compare , run a remote display with help of cat command line, with this :
tkdiff <(ssh system#{external_IP}1 'cat /usr/system/.profile') <(ssh system#{external_IP}2 'cat /usr/system/.profile')
In your case to be able to compare with the local .profile file this :
tkdiff /usr/system/.profile <(ssh system#{external_IP} 'cat /usr/system/.profile')
Do you have just try with the simple diff command line (with -b -B option to remove blank line and space comparaison):
diff -b -B /usr/system/.profile <(ssh system#{external_IP} 'cat /usr/system/.profile')

Source for fancy_echo usage and documentation

I was looking starting point for an install script that will allow me to automatically provision a new or re-imaged computer and came across one by thoughtbot. However, it makes frequent use of a command that I'm not familiar with, fancy_echo.
fancy_echo() {
local fmt="$1"; shift # shellcheck disable=SC2059
printf "\n$fmt\n" "$#"
}
It's also used in this script by dockyard:
fancy_echo "This script will setup your laptop"
fancy_echo "If you want to reuse your old SSH key, copy your SSH config over before running this script"
fancy_echo "During installation, it will ask for your sudo password a few times"
Since this is run in the command line and looks like bash, I've tried the man pages, the standalone GNU info system and the --help option, all with no luck. I presume it prints to the screen but I don't know, so I'm asking. Here are my questions:
What is fancy_echo and how does it differ from echo?
What is a good source of documentation on it?
It's not a standard command, there's no documentation, it's just the function whose definition you copied, which is internal to that package.
fancy_echo format_string arg arg arg....
is equivalent to
printf format_string arg arg arg....
except that it adds newlines around the output.

Adding a tab in a Shell script

So I have an extremely simple shell script, where it inputs an IP address and a domain name in the hosts file of a person's computer. For "development purposes only!" it works fine, it just inputs the IP address and domain name like so
192.168.53.215dev.env.os
192.168.53.215dev.source.os
Where I want it to input it like this:
192.168.53.215 dev.env.os
192.168.53.215 dev.source.os
So basically I want it to add space between the IP address and the domain name, unfortunately I can't really figure it out. Any help would be appreciated, this is a simple script though and shouldn't be cluttered with an over complicated script. Please keep it simple and explain exactly what you're doing I would like to learn it not have it done for me thanks!
Here is the code:
do shell script "/usr/bin/printf \"\\n# Add #####'s ip for Sourcebox\\n192.168.53.215\\dev.env.os\\n192.168.53.215\\dev.source.os\\n\" >> /etc/hosts; /usr/bin/dscacheutil -flushcache" with administrator privileges
Using the -e flag with echo in a bash script will allow you to output tabs.
echo -e "this\thas\ttabs"
The printf can be used as below mentioned for getting tab space
printf "\t"

Resources