Jesse Harris IT

A blog about IT and other things I find interesting

Apple Crumble

September 30, 2019 — Jesse Harris

mum is visiting today and is making an apple crumble with a bunch of spare apples.

Read more...

Comments? Tweet  

Dead simple pancakes

August 18, 2018 — Jesse Harris

This recipe is from taste.com.au. I don't make any changes to it (apart from double it), but I like to transcribe some of my old favs onto my own site incase they go away one day.

Ingrediants

  • 4 eggs
  • 3 and 1/2 cups of milk
  • 2 teaspoon vanilla essence
  • 4 cups of s/r flour
  • 2/3 cup of sugar (whatever you have)
  • Butter for frying

Method

  1. Whisk eggs, milk and vanilla together in a jug. Pour flour into a large bowl. Stir in sugar. Make a well in the center. Add milk mixture. Whisk until just combined.

  2. Self explainitory

  3. Consume with ice cream and maple syrup.

Tags: cooking, dessert-recipe, recipe

Comments? Tweet  

Win32 OpenSSH Package

August 14, 2018 — Jesse Harris

I've recently been using Macos at work lately in order to share admin responsibilities across the team. Still suppporting Windows, however there are a couple of tools I use to make working Windows from a Mac simpler.

PowerShell

Microsoft Open-Sourced PowerShell in 2016 and today in 2018, you can get stable installations for Macos, Linux and Windows on github which is often referred to as PSCore.

As an aside, this new version of powershell is not nativly backward compatible with compiled binary modules of the previous "Windows Powershell", however recently in development is a new module: WindowsCompatibility (currently only available on Windows Insider builds) that allows your to import "Windows Powershell" modules into PSCore.

When alpha and beta builds first became available I started testing remote sessions from Linux and Macos to Windows (As I would prefer to work from a unix system at work), but quickly found that the native "Enter-PSSession" wasn't supported from PSCore.

OpenSSH

Around the same time, Microsoft began working with the OpenBSD's OpenSSH project to bring official OpenSSH builds to Windows and the PSCore team found a way to make "Enter-PSSession" work with this.

Packaging PSCore

Packaging PSCore is very straightforward and I won't go into detail here. Suffice it to say that PSCore is released as an MSI and these are very simple to deploy using tools like Configuration Manager.

OpenSSH Package

Essentially I created a Windows Powershell script which follows the installation directions on the Win32 OpenSSH github Installation page.

The Scripts

Deploying an application using scripts in Configuration Manager, usually requires 3 scripts, and this case is no exception. I have provided the all needed scripts below:

Install.ps1

[CmdLetBinding()]
Param()

#region Helper functions
function Get-Path {
    [CmdLetBinding()]
    Param(
        [ValidateSet(
            "Machine",
            "User"
        )]$Context = "User",
        [Switch]$Raw
    )
    If ($Context -eq "Machine") {
        $Root = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager'
    } else {
        $Root = 'HKCU:'
    }
    If ($Raw){
        Get-ItemPropertyValue -Path "$Root\Environment" -Name Path
    } Else {
        Try {

            (Get-ItemPropertyValue -Path "$Root\Environment" `
                -Name Path -EA SilentlyContinue) -split ';'
        } Catch {
            Write-Warning "No user environment variables found"
        }
    }
}

function Add-Path {
    [CmdLetBinding()]
    Param(
        [Parameter(Mandatory=$True)]
        [ValidateScript({
            if (Test-Path -Path $_) {
                $True
            } else {
                throw "Unable to validate path $_"
            }
            })]$Path,
        [ValidateSet(
            "Machine",
            "User"
        )]$Context
    )

    Write-Verbose "Adding $Path to environment"
    if ($Context -eq 'Machine') {
        If (! $Path -in (Get-Path -Context Machine)){
            Write-Verbose "Adding $Path to machine context"
            setx /m PATH "$(Get-Path -Context Machine -Raw);$Path"
        }
    } else {
        Write-Verbose "Adding $Path to user context"
        If (! $Path -in (Get-Path -Context User)){
            Write-Verbose "Adding $Path to user context"
            setx PATH "$(Get-Path -Context Use -Raw);$Path"
        }
    }
}

function New-SymbolicLink {
Param($Link,$Target)
    If (-Not (Test-Path -Path $Link)){
        If ((Get-Item $Target).PSIsContainer) {
            cmd.exe /c mklink /D $Link $Target
        } Else {
            cmd.exe /c mklink $Link $Target
        }
    }
}
#endregion

# Extract OpenSSH
$Archive = Get-ChildItem -Filter *.zip
Expand-Archive -Path $Archive -DestinationPath $env:ProgramFiles
Rename-Item -Path $Env:ProgramFiles\OpenSSH-Win64 -NewName OpenSSH

#Add InstallDir to Path
Add-Path -Path $Env:ProgramFiles\OpenSSH -Context Machine -Verbose

# Configure OpenSSH
& $Env:ProgramFiles\OpenSSH\install-sshd.ps1

# Start sshd service

Start-Service -Name sshd

# Set service startup

Set-Service sshd -StartupType Automatic
Set-Service ssh-agent -StartupType Automatic

# Setup pwsh link to work around 
# https://github.com/PowerShell/Win32-OpenSSH/issues/784
# Find PSCore Install and Make symbolic link

$PSCoreDir = Get-ChildItem -Path $env:ProgramFiles\PowerShell `
    -Directory | Select-Object -Last 1
New-SymbolicLink -Link $env:SystemDrive\pwsh -Target $PSCoreDir.FullName

# Enable Password Authentication and set pwsh as default shell
$NewConfig = Get-Content -Path $Env:ProgramData\ssh\sshd_config | 
    ForEach-Object {
    Switch ($_) {
        {$_ -match '^#PasswordAuthentication\syes'} {$_.replace('#','')}
        {$_ -match '^#PubkeyAuthentication\syes'} {$_.replace('#','')}
        {$_ -match '^Subsystem\s+sftp\s+'} {
            'Subsystem    powershell c:\pwsh\pwsh.exe -sshs -NoLogo -NoProfile'
        }
        Default {$_}
    }
}
# Update sshd config
Set-Content -Path $Env:ProgramData\ssh\sshd_config -Value $NewConfig `
    -Force

# Restart sshd
Restart-Service sshd

Uninstall.ps1

[CmdLetBinding()]
Param()

#region Helper functions

    function Remove-SymbolicLink {
Param($Link,$Target)
    If (Test-Path -Path $Link){
        If ((Get-Item $Target).PSIsContainer) {
            cmd.exe /c rmdir $Link

        } Else {
            cmd.exe /c del $Link

        }

    }

    }

function Get-Path {
    [CmdLetBinding()]
        Param(
                [ValidateSet(
            "Machine",
            "User"

                    )]$Context = "User",
        [Switch]$Raw

             )
            If ($Context -eq "Machine") {
        $Root = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager'

            } else {
        $Root = 'HKCU:'

            }
    If ($Raw){
        Get-ItemPropertyValue -Path "$Root\Environment" -Name Path

    } Else {
        Try {

            (Get-ItemPropertyValue -Path "$Root\Environment" `
                -Name Path -EA SilentlyContinue) -split ';'

        } Catch {
            Write-Warning "No user environment variables found"

        }

    }

}

function Remove-Path {
    [CmdLetBinding()]
        Param(
        [Parameter(Mandatory=$True)]
        $Path,
        [ValidateSet(
            "Machine",
            "User"

            )]$Context

             )

    Write-Verbose "Removing $Path from environment"
    if ($Context -eq 'Machine') {
        If ($Path -in (Get-Path -Context Machine)){
            Write-Verbose "Removing $Path from machine context"
            $NewPath = ""
            Get-Path -Context Machine | Where-Object {
                $psItem -ne $Path -and
                $psItem -ne ""

            } ForEach-Object {
                    $NewPath += "$psItem;"

            }
            setx /m PATH "$NewPath"

        }

    } else {
        Write-Verbose "Removing $Path from user context"
            If ($Path -in (Get-Path -Context User)){
            Write-Verbose "Removing $Path from user context"
            $NewPath = ""
            Get-Path -Context User | Where-Object {
                $psItem -ne $Path -and
                $psItem -ne ""

            } ForEach-Object {
                    $NewPath += "$psItem;"

            }
            setx PATH "$NewPath"

            }

    }

}

#endregion

& $Env:ProgramFiles\OpenSSH\uninstall-sshd.ps1

# Extract OpenSSH
Remove-Item -Path $env:ProgramFiles\OpenSSH -Recurse -Force
Remove-Path -Path $env:ProgramFiles\OpenSSH -Context Machine -Verbose

# Find PSCore Install and remove symbolic link

$PSCoreDir = Get-ChildItem -Path $env:ProgramFiles\PowerShell -Directory | Select-Object -Last 1
Remove-SymbolicLink -Link $env:SystemDrive\pwsh -Target $PSCoreDir.FullName

# Remove old config
Remove-Item -Path $env:ProgramData\ssh -Recurse -Force

Detect.ps1

$AssumeInstalled = $True

If (-Not (Test-Path $Env:ProgramFiles\OpenSSH)) {
    $AssumeInstalled = $False

}

If (-Not (Test-Path $Env:SystemDrive\pwsh)) {
    $AssumeInstalled = $False

}

If (-Not (Get-Service sshd -ErrorAction SilentlyContinue)) {
    $AssumeInstalled = $False

}

If ($AssumeInstalled) {
    Write-Output "True"

}

Using OpenSSH with Powershell

Now that I have used these scripts to deploy OpenSSH and PSCore, I can PSRemote to a PC using my Mac.

The old way to use "Enter-PSSession" was by specifying the ComputerName parameter like so:

PS\> Enter-PSSession -ComputerName Blah

However, when using OpenSSH with a PS Session you do the following:

PS\> Enter-PSSession -HostName Blah -UserName MrBlah

You could also setup a session in a variable and resue it multiple times in a session:

PS\> $s = New-PSSesssion -HostName Blah -UserName MrBlah
PS\> Enter-PSSession -Session $s

[Blah] PS\>

I hope you have found this usefull.

Tags: powershell, pscore, openssh, windows, macos

Comments? Tweet  

Snaps on Gentoo

August 12, 2018 — Jesse Harris

Why?

Many will think it is heresy to put binary packages on a Gentoo system let alone a package system which encourages binary packages to come with their own set of shared libraries.

While I tend to agree, the practicality of sticking to this arrangement can be difficult for a couple of cases. Here are a few I can think of:

  • Source not available
  • No binary package or source ebuild for Gentoo
  • ebuild takes too long to compile

In the case of ebuilds taking too long (eg. chromium), I have a limited budget and can't really afford to leave my power hungry desktop on 24/7 to keep chromium builds up-to-date.

Here are a quick list of software that I use which fall into one of these categories:

  • Citrix Reciever
  • Powershell (Available as source, but no ebuild and I haven't had the time to try write one myself)
  • Minecraft (Gaming with the kids)
  • Discord (Chatting with games)
  • Chromium (Primarily a firefox user, but have some trouble with getting it to see and work with Citrix)

With my excuses for putting snap's on Gentoo out of the way, here is how I've got it working for my systems.

Overlay

There are a few overlay's for Gentoo out there. Even an official one maintained (or as the case may be, unmaintained) by zyga from Canonical. I tried that one, and many of the forks with no such luck.

After googling around I stumbled on a thread on snapcraft.io and a post from user jamesb192 about the progress on their snapd overlay.

JamesB192 overlay works, but it doesn't have an overlay.xml file for adding with layman. To overcome this, I've hosted one on my site here. You can add this to your system using overlay like this:

        echo app-portage/layman git >> /etc/portage/package.use/layman
        emerge app-portage/layman
        layman -o http://jesseharrisit.com/overlay.xml -f -a JamesB192

Now that you have the overlay installed should be able to emerge snapd like so:

        emerge app-emulation/snapd

Note - You may need to adjust your kernel config and the ebuild is pretty good at highlighting which options need to be set.

Issues

During my testing of snaps on Gentoo, I've come across a couple of issues that either have been solved or could be solved in the ebuild

  1. snap packages only install and run as root (This was solved by setting suid on /usr/lib64/snapd/snap-confine, and solved in ebuild 2.34)
  2. /var/lib/snapd not created (manually mkdir the directory)

Final thoughts.

Snap packages feel like a great augmentation for Gentoo. It allows me to keep using Gentoo as a daily driver and augment some of it's missing packages with packages from more popular distros.

Tags: gentoo, snaps, overlay

Comments? Tweet  

Downgrade Gentoo from testing to stable

August 05, 2018 — Jesse Harris

At some point in my main Gentoo boxes life I added the ~amd64 keyword into my make.conf. I don't remeber why I did this, but I can't think of a reason I need my entire install to be bleeding edge.

I did some googling around on the best approach to achieve this and from what I read on forums, having a bunch of testing packages downgrade to stable is not such a good idea.

One reason might be that per app config files are usually only designed to be backward compatible, not forward compatible.

At any rate, the idea is to gather a list of currently installed testing packages and add them to package.keywords for their current version.

With this method, eventually those packages will become stable.

The method I used is basically from the sabayon wiki with a few tweaks.

  1. First, edit make.conf ACCEPT_KEYWORDS to:

    ACCEPT_KEYWORDS=amd64
    
  2. Now use equery, sed and grep to construct a new packge.keywords

    equery -C -N list -F '=$cpv $mask2' '*' | \
        grep \~ | sed 's/\[~amd64 keyword\]/~amd64/' > \
        /etc/portage/package.keywords/testpackages
    

    Basically I added '-C' to remove colours and grep

  3. Examine testpackages for sanity, and then test with a world upgrade.

    emerge --ask --update --newuse --deep --with-bdeps=y @world
    
    
    These are the packages that would be merged, in order:
    
    
    Calculating dependencies... done!
    
    
    Nothing to merge; quitting.
    

Tags: gentoo, portage

Comments? Tweet  

Ripping an album from youtube - CLI Style

May 28, 2018 — Jesse Harris

With the advent of Spotify, Apple Music, Youtube, Pandora and many other streaming music services, the need to have local mp3 files doesn't crop up very often. However, my kids either have cheap mp3 players or use their 3ds's to play local mp3 files.

This post is a quick tip on ripping an album from youtube using a web browser and a few cli apps. Remember, most tasks don't need a bloated gui to be done efficiently.

Requirement

  1. A Web browser that can play youtube videos
  2. Youtube-dl
  3. ffmpeg
  4. Bash

Prep work

Install ffmpeg

Ubuntu

sudo apt-get install ffmpeg -y

Fedora

sudo yum install ffmpeg

Gentoo

sudo emerge ffmpeg

Install Youtube-DL

If your on a Debian or Ubuntu flavor of linux

sudo apt-get install youtube-dl -y

Fedora

sudo yum install youtub-dl

On my favourite, Gentoo

pip3 install youtube-dl --user

Download the album

At this point you have all the tools you need to get the job done. Have a browse around on youtube to find the album you want an offline copy of and copy the url of the page. Then from a command prompt:

mkdir ~/tmp
cd ~/tmp
youtube-dl -x --audio-format mp3 https://youtube.com/fullurltovideo

Create a list file

While the audio file is downloading, your going to want to create a simple txt file which lists the tracks, titles and start and end timings. I simply fast forwarded through each track toward the end of the song and made note of the mintes and seconds. I created a file with each line representing a track in the album with the following details:

Track Number-Track title-Start duration-End duration

The durations are in the form of HH:MM:SS. Here is what my file looks like:

cat ~/tmp/list.txt
01-The Greatest Show-00:0:00-5:08
02-A Million Dreams-00:5:08-9:38
03-A Million Dreams Reprise-00:9:39-10:38
04-Come Alive-00:10:38-14:25
05-The Other Side-00:14:25-17:58
06-Never Enough-00:17:58-21:28
07-This Is Me-00:21:38-25:23
08-Rewrite the Stars-00:25:23-28:59
09-Tightrope-00:28:59-32:50
10-Never Enough (Reprise)-00:32:50-34:14
11-From Now On-00:34:14-40:12

Split the audio to seperate mp3's

Now that my file has finished downloading, I can convert the file into seperate song files Here is the little bash script I wrote to split the file based on the contents of the list.txt file

cat splitsong.sh
#!/bin/bash

while read -r p; do
    TRACK=$(echo "$p" | awk -F- '{print $1}')
    TITLE=$(echo "$p" | awk -F- '{print $2}')
    START=$(echo "$p" | awk -F- '{print $3}')
    END=$(echo "$p" | awk -F- '{print $4}')
    FILENAME="${TRACK} - The Greatest Showman - ${TITLE}.mp3"
    ffmpeg -i "$2" -acodec copy -ss "$START" -to "$END" "${FILENAME}" < /dev/null
done <"$1"

I then execute the file like this:

chmod +x splitsong.sh
./splitsong.sh list.txt 'Some Sound Track List-qDZLSHY1ims.mp3'

And the whole thing is over in a matter of seconds.

Tags: bash-tips, mp3, ffmpeg, cli, script, youtube, music, linux

Comments? Tweet  

How I Code

May 24, 2018 — Jesse Harris

Updated 17/08/2018

Coding can be fun. I've enjoyed coding from a young age, starting with GW-Basic at maybe 6, 7, or 8.

I remember my brother Alex seemed like a real genius with the computer (an IBM clone made by Acer 8086 XT). Using Basic he could make the computer do anything and was writing his own games.

Back then, editing code we would laugh at today and we take the humble text editor for granted. Take this example, you would type list to see your code:

    >LIST

    10 PRINT "WELCOME TO JESSES GAME"
    20 PRINT "ENTER YOUR NAME"
    30 $I = INPUT
    40 PRINT "WELCOME $I, STRAP YOURSELF IN"

To edit a line of code you would re-write it by typing it in, line number and all.

    20 PRINT "ENTER YOUR FULL NAME"

And to insert a line, start a line with a number between existing lines

    31 $A=$I

When you ran out of in-between-lines there was a command you could run to reindex your lines which would space them all out 10 between each other.

Anyhow, when my Dad was about the same age as I am now (35), he went back to University to study Computer Science. I remember him bringing home Slackware and RedHat on floppies, which we would install and he would give me lessons on using Vi possibly vim, but I didn't know at the time. (This is probably around 1996).

Since finishing School and entering the workforce I have mostly worked in Windows environments. Even still, with the occasionaly need to touch GNU/Linux at work and often testing Distro's at home I would always feel more efficient when using Vi/m.

My feeling when using another editor is that moving around and changing text feels so lethargic when done one button at a time. This drove me in recent years to keep a copy in my home profile.

Around 2011 I switched from VBScript and the occasional perl script to writing fulltime in Powershell, so it made sense to try a few different editors which are more native to the Windows platform. I tried Visual Studio Code, Powershell ISE, Notepad++ and still kept coming back to vim.

Visual Studio Code is a great alternative, and it's Powershell extensions are very good. Hoever being an electron app, it suffers from performance and memory consumption issues. I love squeezing every drop of battery out of my PC and when you see 7mb RAM on Vim vs 500Mb+ on VSCode, you might rethink your choices.

Therefore I've resorted to delving into the world of customizing vim and setting up plugins.

One of the main things I'm trying to acheive is a cross platform configuration. You see, at work I'm on Windows and MacOs and at home I'm on Gentoo Linux. So I have written my .vimrc file to work on any platform. I usually sync it with OneDrive for Business and symlink it into my linux/mac/Windows home directory with a seperate setup script. Without further ado, here it is with some comments

.vimrc

if has("win32")                               " Check if on windows \
                                              " Also supports has(unix)
    source $VIMRUNTIME/mswin.vim              " Load a special vimscript \
                                              " ctrl+c and ctrl+v support
    behave mswin                              " Like above
    set ff=dos                                " Set file format to dos
    let os='win'                              " Set os var to win
    set noeol                                 " Don't add an extra line \
                                              " at the end of each file
    set nofixeol                              " Disable the fixeol : Not \
                                              " not sure why this is needed
    set backupdir=~/_vimtmp,.                 " Set backupdir rather \
                                              " than leaving backup files \
                                              " all over the fs
    set directory=~/_vimtmp,.                 " Set dir for swp files \
                                              " rather than leaving files \
                                              " all over the fs
    set undodir=$USERPROFILE/vimfiles/VIM_UNDO_FILES " Set persistent undo\
                                              " files
                                              " directory
    let plug='$USERPROFILE/.vim'              " Setup a var used later to \
                                              " store plugins
    set shell=powershell                      " Set shell to powershell \
                                              " on windows
    set shellcmdflag=-command                 " Arg for powrshell to run
else
    set backupdir=~/.vimtmp,.
    set directory=~/.vimtmp,.
    set undodir=$HOME/.vim/VIM_UNDO_FILES
    let uname = system('uname')               " Check variant of Unix \
                                              " running. Linux|Macos
    if uname =~ "Darwin"                      " If MacOS
        let plug='~/.vim'
        let os='mac'                          " Set os var to mac
    else
        if isdirectory('/mnt/c/Users/jpharris')
            let plug='/mnt/c/Users/jpharris/.vim'
            let os='wsl'
        else
            let plug='~/.vim'
            let os='lin'
        endif
    endif
endif

execute "source " . plug . "/autoload/plug.vim"
if exists('*plug#begin')
    call plug#begin(plug . '/plugged')       " Enable the following plugins
    Plug 'tpope/vim-fugitive'
    Plug 'junegunn/gv.vim'
    Plug 'junegunn/vim-easy-align'
    Plug 'jiangmiao/auto-pairs'
    "Plug 'vim-airline/vim-airline'          " Airline disabled for perf
    Plug 'morhetz/gruvbox'
    Plug 'ervandew/supertab'
    Plug 'tomtom/tlib_vim'
    Plug 'MarcWeber/vim-addon-mw-utils'
    Plug 'PProvost/vim-ps1'
    Plug 'garbas/vim-snipmate'
    Plug 'honza/vim-snippets'
    call plug#end()
endif
                                             " Remove menu bars
if has("gui_running")                        " Options for gvim only
    set guioptions -=m                       " Disable menubar
    set guioptions -=T                       " Disable Status bar
    set lines=50                             " Set default of lines
    set columns=80                          " Set default of columns
    if os =~ "lin"
        set guifont=Fira\ Code\ 12
    elseif os =~ "mac"
        set guifont=FiraCode-Retina:h14
    else
        set guifont=Fira_Code_Retina:h12:cANSI:qDRAFT
        set renderoptions=type:directx
        set encoding=utf-8
    endif
    set background=dark
    colorscheme gruvbox
else
    set mouse=a
    if has('termguicolors')
        set termguicolors                    " Enable termguicolors for \
                                             " consoles which support 256.
        set background=dark
        colorscheme gruvbox
    endif
endif

if has("persistent_undo")
    set undofile                             " Enable persistent undo
endif

colorscheme evening                          " Set the default colorscheme
                                             " Attempt to start vim-plug

syntax on                                    " Enable syntax highlighting
filetype plugin indent on                    " Enable plugin based auto \
                                             " indent
set tabstop=4                                " show existing tab with 4 \
                                             " spaces width
set shiftwidth=4                             " when indenting with '>', \
                                             " use 4 spaces width
set expandtab                                " On pressing tab, insert 4 \
                                             " spaces
set number                                   " Show line numbers

" Map F5 to python.exe %=current file
nnoremap <silent> <F5> :!clear;python %<CR>
" Remap tab to auto complete 
imap <C-@> <C-Space>
" Setup ga shortcut for easyaline in visual mode
nmap ga <Plug>(EasyAlign)
" Setup ga shortcut for easyaline in normal mode
xmap ga <Plug>(EasyAlign)"

Link to vimrc on github

Tags: vim, coding, windows, linux, macos

Comments? Tweet