Producing a profile
I switch between alot of different VMs at work and several environments at home now as well. As my linux skills grow I’m trying to develop my knowledge in a specific direction. When I switch between Ubuntu, Redhat, Mac I get annoyed when a tool I’m learning does not work the way I expect it too. Examples of this are hotkeys, coloring, aliases, and the availability of a tool in the first place. Over the years I’ve spent alot of time getting a basic thing I know works to work on a different linux distribution. But I’m too the point now where I’d like to develop a deeper level of knowledge and build ontop of the new skills I’m acquiring.
My strategy is to:
- Stick with tools that are ubiquitous. This means coreutils, builtins, or the widely available standard tool. (Example: curl, vim)
- Rely on the system documentation about the tool. I’ve been using internet searchs for years to help me along with linux, that knowledge has not always been sticky. Now, when I learn something I go back to the system documentation (man pages) for a reference so that knowledge will stick and I know where to look for the specific implementation details of that tool on a new system.
- Solve my problems using the tools I have. That could mean doing things the ‘hard way’ the first time around, but eventually I seem to figure out a way to turn it into an ‘easy method’ after developing or acquiring additional knowledge.
- Bring my tools with me. This means that if I’m investing time configuring a tool I want to be able to bring that investment with me to whichever system I’m thrown on.
To address the last point ‘bring my tools with me’ I’ve been working on creating dotfiles, hosted on github, that I can just pull into any system I’m using. I want to be able to pull in this configuration, do my work, then leave the system in the state it was in before I arrived. For this method to work I need the system to have git installed.
In working through this project I’ve still ended up spending alot of time delving into the arcana of linux settings, but I feel that after I’m able to put it into the profile it’s ‘checked off’ if you will. Hopefully, I won’t have to resolve the same problem in the future or I’ve found reference in the system for the tool which will allow more targeted searching next time around.
Two problems I’ve dealt with recently are: - Character encoding or why can’t I see ▷ ⋅ - Sourcing my profiles through a script
The first problem arose while working on a vimrc file. I have started to use this line which represents spaces and tabs in a way that I like visually:
set list listchars=tab:▷⋅,trail:⋅,nbsp:⋅
This line works great on my mac, everything is beautiful. But when I pull it onto a linux system vim will prompt me with an error when loading each file and the character is gobbilty gock when I look at it in the config file. So what’s up?
Turns out to be a language issue. The character is a unicode character and on my mac the terminal was installing the correct character set to view it. In the linux systems I was configuring, the proper encoding was not being used. This article discusses utf-8 comprehensively. It is more than I need to know, but pointed me in the direction of the locale command which ended up helping solve my problem.
$ locale
LANG="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_CTYPE="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_ALL=
This gives me the settings I like, but what do they mean? Well, the bottom of the locale man page references localedef which contains the real solution to my problem. > LANG > Provide a default value for the internationalization variables that are unset or null. If LANG is unset or null, the corresponding value from the implementation-dependent default locale will be used. If any of the internationalization variables contains an invalid setting, the utility will behave as if none of the variables had been defined. > LC_ALL > If set to a non-empty string value, override the values of all the other internationalization variables.
So, long story short I’m just setting my encoding to UTF-8 on all terminals now and will not worry about it more unless asked too.
The second problem relates to the script I’ve been testing for configuring my environment. I’ll backup all the configuration files I want to modify, then create a symbolic link to the fields from my git repo in their place. But, after executing the script I would still have to manually source the files after executing it ala ‘source ~/.bashrc’.
I execute the script this way:
./init.sh
When I would add my command ‘source ~/.bashrc’ to the script, it would appear to execute, but my environment would not change. What gives?
The clue is from ‘man bash’: > source filename [arguments] > Read and execute commands from filename in the current shell environment and return the exit status of the last command executed from filename.
I’ve been doing ./command for years, not really understanding what is going on. When using the ./ or sh command a sub-process or fork is created of the current shell when the script is executed. When the ‘source’ command is used it will modify the environment for the shell it is in (i.e. the forked subprocess) and not the shell being displayed on my terminal. So, the solution is to execute my script using ‘source init.sh’ instead, this causes the changes being applied in the script (including ‘source .bashrc’) to apply to the shell I am in, not the shell of the subprocess.
I admit these explanations are a little hand-wavey, but my goal is not to become an expert on shell implementation details or character encoding! Really I’m trying to solve my short-term problem quickly and move on to developing a skill-set around the tool I’m really focusing on. However, what I’ve learned here is that next time around when I hit a more sophisticated problem I can use the ‘locale’ and ‘bash’ man pages to get more details about the next problem I hit!